Index: qemud/qemud.c =================================================================== RCS file: /data/cvs/libxen/qemud/qemud.c,v retrieving revision 1.109 diff -u -p -r1.109 qemud.c --- qemud/qemud.c 4 Nov 2008 23:22:06 -0000 1.109 +++ qemud/qemud.c 5 Nov 2008 14:51:50 -0000 @@ -128,6 +128,116 @@ static void sig_handler(int sig, siginfo errno = origerrno; } +static FILE *error_out = NULL; +static FILE *info_out = NULL; +static int debug_activated = 0; + +#ifdef ENABLE_DEBUG + +/* + * Signal entry point on USR2 we can't do anything at that point except + * log the signal and have qemudToggleDebug called when back into the + * main loop. + */ +static void sig_debug(int sig, siginfo_t * siginfo, void* context) { + sig_handler(sig, siginfo, context); +} + +/* + * Debug the state of a client + */ +static void qemudDumpDebugClient(struct qemud_client *client) { + if (client->magic != QEMUD_CLIENT_MAGIC) { + qemudLog(QEMUD_DEBUG, + _("\nQEmud client: invalid magic %X, skipping\n"), + (unsigned int) client->magic); + return; + } + qemudLog(QEMUD_DEBUG, _("QEmud client: fd %d readonly %d mode %d"), + client->fd, client->readonly, client->mode); + + /* TODO: more complete dump of state, especially the connection */ +} + +/* + * Debug the state of a server + */ +static void qemudDumpDebugServer(struct qemud_server *server) { + struct qemud_client *client; + + if (server == NULL) { + qemudLog(QEMUD_DEBUG, "%s", + _("QEmud server: NULL pointer\n")); + return; + } + qemudLog(QEMUD_DEBUG, + _("QEmud server: listening on %d sockets, %d clients\n"), + server->nsockets, server->nclients); + + client = server->clients; + + while (client != NULL) { + qemudDumpDebugClient(client); + client = client->next; + } +} + +/* + * Toggle the debug status on/off, on on create a new temporary + * debug file and start saving the output there + * It is called when the signal USR2 is received. + */ +static void qemudToggleDebug(struct qemud_server *server) { + if (debug_activated == 0) { + char path[50] = "/tmp/libvirt_debug_XXXXXX"; + int fd = mkstemp(path); + if (fd >= 0) { + error_out = fdopen(fd, "a"); + if (error_out != NULL) { + info_out = error_out; + debug_activated = 1; + qemudDumpDebugServer(server); + } else { + qemudLog(QEMUD_ERR, + "%s", _("Failed to create temporary debug file")); + error_out = stderr; + } + } else { + qemudLog(QEMUD_ERR, + "%s", _("Failed to get temporary debug file")); + } + } else { + debug_activated = 0; + fclose(error_out); + error_out = stderr; + info_out = stdout; + } +} +#endif + +/* + * Set up the debugging environment + */ +static void qemudInitDebug(void) { +#ifdef ENABLE_DEBUG + struct sigaction oldact; + struct sigaction sig_action; + + /* + * if there is already an handler, leave it as is to + * avoid disturbing the application's behaviour + */ + if (sigaction (SIGUSR2, NULL, &oldact) == 0) { + if (oldact.sa_handler == NULL && oldact.sa_sigaction == NULL) { + sig_action.sa_sigaction = sig_debug; + sigaction(SIGUSR2, &sig_action, NULL); + } + } +#endif + error_out = stderr; + info_out = stdout; +} + static void qemudDispatchClientEvent(int fd, int events, void *opaque); static void qemudDispatchServerEvent(int fd, int events, void *opaque); static int qemudRegisterClientEvent(struct qemud_server *server, @@ -260,7 +370,11 @@ qemudDispatchSignalEvent(int fd ATTRIBUT siginfo.si_signo); server->shutdown = 1; break; - +#ifdef ENABLE_DEBUG + case SIGUSR2: + qemudToggleDebug(server); + break; +#endif default: qemudLog(QEMUD_INFO, _("Received unexpected signal %d"), siginfo.si_signo); @@ -306,7 +420,7 @@ void qemudLog(int priority, const char * va_start(args, fmt); - if (godaemon) { + if ((godaemon) && (!debug_activated)) { int sysprio = -1; switch(priority) { @@ -336,22 +450,22 @@ void qemudLog(int priority, const char * switch(priority) { case QEMUD_ERR: case QEMUD_WARN: - vfprintf(stderr, fmt, args); - fputc('\n', stderr); + vfprintf(error_out, fmt, args); + fputc('\n', error_out); break; case QEMUD_INFO: - if (verbose) { - vprintf(fmt, args); - fputc('\n', stdout); + if ((verbose) || (debug_activated)) { + vfprintf(info_out, fmt, args); + fputc('\n', info_out); } break; #ifdef ENABLE_DEBUG case QEMUD_DEBUG: - if (verbose) { - vprintf(fmt, args); - fputc('\n', stdout); + if ((verbose) || (debug_activated)) { + vfprintf(info_out, fmt, args); + fputc('\n', info_out); } break; #endif @@ -2163,12 +2277,14 @@ int main(int argc, char **argv) { return 2; default: - fprintf (stderr, "libvirtd: internal error: unknown flag: %c\n", + fprintf (error_out, "libvirtd: internal error: unknown flag: %c\n", c); exit (1); } } + qemudInitDebug(); + if (godaemon) { openlog("libvirtd", 0, 0); if (qemudGoDaemon() < 0) {