On Thu, Dec 23, 2010 at 09:05:58AM -0700, Eric Blake wrote: > On 12/23/2010 02:07 AM, Hu Tao wrote: > > --- > > No commit message beyond the title? > > > @@ -208,6 +211,7 @@ typedef struct __vshCmd { > > typedef struct __vshControl { > > char *name; /* connection name */ > > virConnectPtr conn; /* connection to hypervisor (MAY BE NULL) */ > > + virDomainPtr dom; > > No comment as to it's purpose? Will update it if I update the patch. > > > vshCmd *cmd; /* the current command */ > > char *cmdstr; /* string with command */ > > int imode; /* interactive mode? */ > > @@ -221,6 +225,9 @@ typedef struct __vshControl { > > int log_fd; /* log file descriptor */ > > char *historydir; /* readline history directory name */ > > char *historyfile; /* readline history file name */ > > + > > + virMutex mutex; > > + virThreadPoolPtr threadPool; > > Likewise. Will update it if I update the patch. > > > @@ -509,6 +518,44 @@ static void vshCatchDisconnect(int sig, siginfo_t * siginfo, > > if ((sig == SIGPIPE) || (siginfo->si_signo == SIGPIPE)) > > disconnected++; > > } > > +#endif > > + > > +#ifdef SIGINT > > Unnecessary ifdef - SIGINT is available on all platforms (it is required > by C). > > > +static void vshCatchInt(int sig, siginfo_t *siginfo, > > + void *context ATTRIBUTE_UNUSED) { > > + vshControl *ctl = &_ctl; > > + vshCmd *cmds, *c; > > + char *cmdStr = NULL; > > + > > + virMutexLock(&ctl->mutex); > > + if (!ctl->dom) > > + goto error; > > + > > + if (virAsprintf(&cmdStr, "domjobabort %s", ctl->dom->name) < 0) > > _BIG_ no-no. virAsprintf calls malloc(), which is NOT signal-safe (that > is, if the signal arrived while some other thread was in the middle of a > malloc(), you've just caused deadlock). The only safe thing to do in a > signal handler is to set some state variables that are then checked in > the main processing loop, when you are back in a safe state to act on a > (minimally-delayed) basis on the signal. > > See how daemon/libvirtd.c uses qemudDispatchSignalEvent (although that's > being rewritten by danpb's factorization into a cleaner rpc > server/client model). > > > + goto error; > > + > > + if ((sig == SIGINT) || (siginfo->si_signo == SIGINT)) { > > + if (!vshConnectionUsability (ctl, ctl->conn)) > > + goto error; > > + > > + vshCommandStringParse(ctl, cmdStr); > > + cmds = ctl->cmd; > > + ctl->cmd = NULL; > > + virMutexUnlock(&ctl->mutex); > > + do { > > + c = cmds; > > + cmds = cmds->next; > > + c->next = NULL; > > + ignore_value(virThreadPoolSendJob(ctl->threadPool, c, true)); > > Continuing in the vein of bad practice - blocking on another thread to > complete inside a signal handler is crazy. But setting up a threadpool I did a copy&paste and forgot to change true to false :) > to handle signals in a separate thread means that your signal-handling > thread is already independently available to cancel the job that is > underway in the primary thread. The intention of setting up a threadpool is to submit another command in a seprate thread while there is already a command being processed. If we do it in one thread, then we will end up with deaklock eventually. Take dump as example: 1. submit command dump 2. polling for reply from RPC server 3. SIGINT(poll is interrupted) 4. submit command domjobabort form signal handler 5. (in remoteIO())there is a priv->waitDispatch, so go to sleep(vifCondWait). The impl of remote driver is thread-aware, and this thread (processing command domjobabort) is supposed to be waken up by the thread that is having priv->waitDispatch(processing command dump). But we are the same thread, so deadlock. Well, I have to say that the patch is nasty. Do you (or anyone) have a good idea to achieve the goal to cancel the active job if user presses Ctrl-C? Thanks. > > > + } while (cmds); > > + } > > + VIR_FREE(cmdStr); > > + return; > > +error: > > + virMutexUnlock(&ctl->mutex); > > + VIR_FREE(cmdStr); > > +} > > +#endif > > > > /* > > * vshSetupSignals: > > @@ -520,17 +567,20 @@ static void > > vshSetupSignals(void) { > > struct sigaction sig_action; > > > > - sig_action.sa_sigaction = vshCatchDisconnect; > > sig_action.sa_flags = SA_SIGINFO; > > sigemptyset(&sig_action.sa_mask); > > > > +#ifdef SIGPIPE > > Might be unnecessary - gnulib guarantees that a working replacement for > SIGPIPE is available on mingw, which is the only platform that lacks it > natively. Oh, but that module is currently LGPLv3+, I'll have to ask on > the gnulib list if people are willing to relax it to LGPLv2+ so we can > use it. > > -- > Eric Blake eblake@xxxxxxxxxx +1-801-349-2682 > Libvirt virtualization library http://libvirt.org > -- Thanks, Hu Tao -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list