[libvirt] [PATCH 1/3] Cancel migration if user presses Ctrl-C when migration is in progress
Wen Congyang
wency at cn.fujitsu.com
Tue Jan 25 07:05:28 UTC 2011
At 01/25/2011 08:37 AM, Eric Blake Write:
> On 01/23/2011 07:20 PM, Wen Congyang wrote:
>> From: Hu Tao <hutao at cn.fujitsu.com>
>> Date: Tue, 11 Jan 2011 15:01:24 +0800
>> Subject: [PATCH 1/3] Cancel migration if user presses Ctrl-C when migration is in progress
>>
>> While migration is in progress and virsh is waiting for its
>> completion, user may want to terminate the progress by pressing
>> Ctrl-C. But virsh just exits on user's Ctrl-C leaving migration
>> in background that user isn't even aware of. It's not reasonable.
>>
>> This patch changes the behaviour for migration. For other
>> commands Ctrl-C still terminates virsh itself.
>>
>>
>> +static bool intCatched = FALSE;
>
> s/Catched/Caught/g
>
> Don't mix FALSE and bool (either int and FALSE, or bool and false; with
> the caveat that int and TRUE/FALSE are historical baggage in this file
> and we are gradually trying to convert them over to bool and true/false).
>
>> +
>> +static void vshCatchInt(int sig ATTRIBUTE_UNUSED,
>> + siginfo_t *siginfo ATTRIBUTE_UNUSED,
>> + void *context ATTRIBUTE_UNUSED)
>> +{
>> + intCatched = TRUE;
>
> Furthermore, POSIX states that variables used to communicate between
> signal handlers and other threads should be [volatile] sig_atomic_t,
> rather than bool (why? because on some platforms where bool is a byte
> and smaller than a machine word, it may result in a read-modify-write
> cycle that could interfere with neighboring bytes, when contrasted with
> a machine word write of using a sig_atomic_t). So use of bool for this
> one variable is non-portable to begin with.
>
>>
>> -static int
>> -cmdMigrate (vshControl *ctl, const vshCmd *cmd)
>> +static void
>> +doMigrate (void *opaque)
>> {
>> + char ret = '1';
>> virDomainPtr dom = NULL;
>> const char *desturi;
>> const char *migrateuri;
>> const char *dname;
>> - int flags = 0, found, ret = FALSE;
>> + int flags = 0, found;
>> + sigset_t sigmask, oldsigmask;
>> + struct {
>> + vshControl *ctl;
>> + vshCmd *cmd;
>> + int writefd;
>> + } *data = opaque;
>
> Rather than declaring the struct inline, let's typedef it in advance, so
> that both caller and consumer share the same struct declaration (that
> way, if we ever have to add to the struct, we only have to do it in one
> place).
>
>> + vshControl *ctl = data->ctl;
>> + vshCmd *cmd = data->cmd;
>> +
>> + sigemptyset(&sigmask);
>> + sigaddset(&sigmask, SIGINT);
>> + if (pthread_sigmask(SIG_BLOCK, &sigmask, &oldsigmask) < 0)
>> + goto out_sig;
>
> Mingw lacks pthread_sigmask, and gnulib doesn't have it (yet). This may
> cause some compilation portability problems to mingw, but I can help
> with that (and it can be a followup patch - I won't make it a condition
> for getting this much-needed improvement in).
>
>> +static int
>> +cmdMigrate (vshControl *ctl, const vshCmd *cmd)
>> +{
>
>> +
>> + if (!(dom = vshCommandOptDomain (ctl, cmd, NULL)))
>
> Style - new code should use vshCommandOptDomain(ctl, without a space.
>
>> +
>> + intCatched = FALSE;
>> + sig_action.sa_sigaction = vshCatchInt;
>> + sig_action.sa_flags = SA_SIGINFO;
>> + sigemptyset(&sig_action.sa_mask);
>> + sigaction(SIGINT, &sig_action, &old_sig_action);
>> +
>> + pollfd.fd = p[0];
>> + pollfd.events = POLLIN;
>> + pollfd.revents = 0;
>> +
>> + ret = poll(&pollfd, 1, -1);
>> + if (ret > 0) {
>> + if (saferead(p[0], &retchar, sizeof(retchar)) > 0) {
>> + if (retchar == '0')
>> + ret = TRUE;
>> + else
>> + ret = FALSE;
>> + } else
>> + ret = FALSE;
>> + } else if (ret < 0) {
>> + if (errno == EINTR && intCatched) {
>> + virDomainAbortJob(dom);
>> + ret = FALSE;
>> + intCatched = FALSE;
>> + }
>
> Don't you need a retry loop here, if you get EINTR but an interrupt was
> not marked as caught?
>
>> + } else {
>> + /* timed out */
>> + ret = FALSE;
>> + }
>> +
>> + sigaction(SIGINT, &old_sig_action, NULL);
>> +
>> + virThreadJoin(&workerThread);
>> +
>> +cleanup:
>> + if (dom)
>> + virDomainFree(dom);
>> + if (p[0] != -1) {
>> + close(p[0]);
>> + close(p[1]);
>
> 'make syntax-check' should have caught these violations (if it didn't,
> then that's something that we should fix). This should be:
unfortunately, 'make syntax-check' does not catch these violations.
>
> cleanup:
> virDomainFree(dom);
> VIR_FORCE_CLOSE(p[0]);
> VIR_FORCE_CLOSE(p[1]);
>
> which avoids issues with double-close, and which avoids useless if
> statements on free-like functions.
>
More information about the libvir-list
mailing list