virlog: Take a special care of syslog when setting new set of log outputs

Now that we're in the critical section, syslog connection can be re-opened
by issuing openlog, which is something that cannot be done beforehand, since
syslog keeps its file descriptor private and changing the tag earlier might
introduce a log inconsistency if something went wrong with preparing a new set
of logging outputs in order to replace the existing one.

Signed-off-by: Erik Skultety <eskultet@redhat.com>
This commit is contained in:
Erik Skultety 2016-03-30 12:38:39 +02:00
parent 4c35229580
commit 640b58abdf

View File

@ -1794,16 +1794,37 @@ virLogFindOutput(virLogOutputPtr *outputs, size_t noutputs,
int int
virLogDefineOutputs(virLogOutputPtr *outputs, size_t noutputs) virLogDefineOutputs(virLogOutputPtr *outputs, size_t noutputs)
{ {
int ret = -1;
int id;
char *tmp = NULL;
if (virLogInitialize() < 0) if (virLogInitialize() < 0)
return -1; return -1;
virLogLock(); virLogLock();
virLogResetOutputs(); virLogResetOutputs();
/* syslog needs to be special-cased, since it keeps the fd in private */
if ((id = virLogFindOutput(outputs, noutputs, VIR_LOG_TO_SYSLOG,
current_ident)) != -1) {
/* nothing can go wrong now (except for malloc) and since we're also
* holding the lock so it's safe to call openlog and change the message
* tag
*/
if (VIR_STRDUP_QUIET(tmp, outputs[id]->name) < 0)
goto cleanup;
VIR_FREE(current_ident);
current_ident = tmp;
openlog(current_ident, 0, 0);
}
virLogOutputs = outputs; virLogOutputs = outputs;
virLogNbOutputs = noutputs; virLogNbOutputs = noutputs;
virLogUnlock();
return 0; ret = 0;
cleanup:
virLogUnlock();
return ret;
} }