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?

>      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.

> @@ -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
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.

> +        } 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   ebl...@redhat.com    +1-801-349-2682
Libvirt virtualization library http://libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to