[libvirt] [PATCH] use sa_handler instead of sa_sigaction when SA_SIGINFO is not defined
Wen Congyang
wency at cn.fujitsu.com
Fri Apr 20 03:35:47 UTC 2012
At 04/20/2012 11:26 AM, Eric Blake Wrote:
> On 04/19/2012 09:10 PM, Wen Congyang wrote:
>> POSIX requires that we use sa_sigaction if sa_flags includes SA_SIGINFO,
>> and that we use sa_handler otherwise. But we still use sa_sigaction
>> when SA_SIGINFO is not defined. Practice says it will work, but theory
>> says we can't rely on it to work.
>
> Not quite what I said. Gnulib guarantees that sa_sigaction will work
> instead of sa_handler, _for the platforms where SA_SIGINFO is not
> defined_, and provided that your handler does not access the 2nd or 3rd
> argument in those situations. That is, gnulib gives us some guarantees
> that POSIX does not, and that allows us to write simpler code that
> assumes SA_SIGINFO just works everywhere, as long as the handler is
> careful with the last two arguments. For all platforms where SA_SIGINFO
> is defined, using just sa_sigaction is fine.
Sorry for my misunderstanding. I will update this patch.
Thanks
Wen Congyang
>
> tools/virsh.c is therefore correct, and only src/rpc/virnetserver.c has
> a bug.
>
>>
>> ---
>> src/rpc/virnetserver.c | 25 +++++++++++++++++++++++--
>> tools/virsh.c | 35 ++++++++++++++++++++++++++++-------
>> 2 files changed, 51 insertions(+), 9 deletions(-)
>>
>> diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
>> index 3965fc2..131ecb4 100644
>> --- a/src/rpc/virnetserver.c
>> +++ b/src/rpc/virnetserver.c
>> @@ -270,8 +270,12 @@ error:
>> }
>>
>>
>> +#ifdef SA_SIGINFO
>> static void virNetServerFatalSignal(int sig, siginfo_t *siginfo ATTRIBUTE_UNUSED,
>> void *context ATTRIBUTE_UNUSED)
>> +#else
>> +static void virNetServerFatalSignal(int sig)
>> +#endif
>
> Yuck. I'm happy with a single three-arg definition as long as we follow
> the gnulib rules about using sa_sigaction and SA_SIGINFO as a pair,
> rather than adding ugly #ifdefs.
>
>> {
>> struct sigaction sig_action;
>> int origerrno;
>> @@ -286,6 +290,7 @@ static void virNetServerFatalSignal(int sig, siginfo_t *siginfo ATTRIBUTE_UNUSED
>> #ifdef SIGUSR2
>> if (sig != SIGUSR2) {
>> #endif
>> + memset(&sig_action, 0, sizeof(sig_action));
>> sig_action.sa_handler = SIG_DFL;
>> sigaction(sig, &sig_action, NULL);
>
> Good catch - that memset (or an explicit setting of sig_action.sa_flags
> = 0) is required; just because Linux behaves sanely for
> sa_handler==SIG_DFL regardless of uninitialized sa_flags does not mean
> all platforms do likewise.
>
>> raise(sig);
>> @@ -362,7 +367,12 @@ virNetServerPtr virNetServerNew(size_t min_workers,
>> * catch fatal errors to dump a log, also hook to USR2 for dynamic
>> * debugging purposes or testing
>> */
>> +#ifdef SA_SIGINFO
>> sig_action.sa_sigaction = virNetServerFatalSignal;
>> + sig_action.sa_flags = SA_SIGINFO;
>
> This one line is important,
>
>> +#else
>> + sig_action.sa_handler = virNetServerFatalSignal;
>> +#endif
>
> this #ifdef stuff is just gross. We should instead copy virsh.c and
> #define SA_SIGINFO 0 if it is not already defined.
>
>> sigaction(SIGFPE, &sig_action, NULL);
>> sigaction(SIGSEGV, &sig_action, NULL);
>> sigaction(SIGILL, &sig_action, NULL);
>> @@ -420,17 +430,28 @@ static sig_atomic_t sigErrors = 0;
>> static int sigLastErrno = 0;
>> static int sigWrite = -1;
>>
>> +#ifdef SA_SIGINFO
>> static void virNetServerSignalHandler(int sig, siginfo_t * siginfo,
>> void* context ATTRIBUTE_UNUSED)
>> +#else
>> +static void virNetServerSignalHandler(int sig)
>> +#endif
>
> Not sure I like the #ifdef here,
>
>> {
>> int origerrno;
>> int r;
>> + siginfo_t temp_siginfo;
>> +
>> +#ifdef SA_SIGINFO
>> + memcpy(&temp_siginfo, siginfo, sizeof(temp_siginfo));
>> +#else
>> + memset(&temp_siginfo, 0, sizeof(temp_siginfo));
>> +#endif
>
> Here, if you start the file with:
>
> #ifndef SA_SIGINFO
> # define SA_SIGINFO 0
> #endif
>
> then here, you can avoid the in-function #ifdef with:
>
> if (SA_SIGINFO)
> memcpy(&tmp_siginfo, siginfo, sizeof(temp_siginfo));
> else
> memset(&temp_siginfo, 0, sizeof(temp_siginfo));
>
>>
>> /* set the sig num in the struct */
>> - siginfo->si_signo = sig;
>> + temp_siginfo.si_signo = sig;
>>
>> origerrno = errno;
>> - r = safewrite(sigWrite, siginfo, sizeof(*siginfo));
>> + r = safewrite(sigWrite, &temp_siginfo, sizeof(temp_siginfo));
>
> This change makes sense (the caller won't get much more than si_siginfo
> out of their virNetServerSignalFunc callback, but at least we are no
> longer passing random memory to the callback on mingw).
>
>> +++ b/tools/virsh.c
>> @@ -579,9 +579,13 @@ out:
>>
>> static volatile sig_atomic_t intCaught = 0;
>>
>> +#ifdef SA_SIGINFO
>> static void vshCatchInt(int sig ATTRIBUTE_UNUSED,
>> siginfo_t *siginfo ATTRIBUTE_UNUSED,
>> void *context ATTRIBUTE_UNUSED)
>> +#else
>> +static void vshCatchInt(int sig ATTRIBUTE_UNUSED)
>> +#endif
>
> Not needed.
>
>> {
>> intCaught = 1;
>> }
>> @@ -591,23 +595,25 @@ static void vshCatchInt(int sig ATTRIBUTE_UNUSED,
>> */
>> static int disconnected = 0; /* we may have been disconnected */
>>
>> -/* Gnulib doesn't guarantee SA_SIGINFO support. */
>> -#ifndef SA_SIGINFO
>> -# define SA_SIGINFO 0
>> -#endif
>
> Keep this, and copy it to virnetserver.c (or even float it to a common
> location, like internal.h).
>
More information about the libvir-list
mailing list