Fix latent portability issue in pgwin32_dispatch_queued_signals().
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 4 Apr 2016 15:13:17 +0000 (11:13 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 4 Apr 2016 15:13:17 +0000 (11:13 -0400)
The first iteration of the signal-checking loop would compute sigmask(0)
which expands to 1<<(-1) which is undefined behavior according to the
C standard.  The lack of field reports of trouble suggest that it
evaluates to 0 on all existing Windows compilers, but that's hardly
something to rely on.  Since signal 0 isn't a queueable signal anyway,
we can just make the loop iterate from 1 instead, and save a few cycles
as well as avoiding the undefined behavior.

In passing, avoid evaluating the volatile expression UNBLOCKED_SIGNAL_QUEUE
twice in a row; there's no reason to waste cycles like that.

Noted by Aleksander Alekseev, though this isn't his proposed fix.
Back-patch to all supported branches.

src/backend/port/win32/signal.c

index 36c6ebd6863e0174eb469c6aba7d7e3f93431e13..640ee9ec644cc2a19d33361e287ed8e5d4814568 100644 (file)
@@ -33,6 +33,7 @@ HANDLE                pgwin32_initial_signal_pipe = INVALID_HANDLE_VALUE;
  */
 static CRITICAL_SECTION pg_signal_crit_sec;
 
+/* Note that array elements 0 are unused since they correspond to signal 0 */
 static pqsigfunc pg_signal_array[PG_SIGNAL_COUNT];
 static pqsigfunc pg_signal_defaults[PG_SIGNAL_COUNT];
 
@@ -105,15 +106,15 @@ pgwin32_signal_initialize(void)
 void
 pgwin32_dispatch_queued_signals(void)
 {
-       int                     i;
+       int                     exec_mask;
 
        EnterCriticalSection(&pg_signal_crit_sec);
-       while (UNBLOCKED_SIGNAL_QUEUE())
+       while ((exec_mask = UNBLOCKED_SIGNAL_QUEUE()) != 0)
        {
                /* One or more unblocked signals queued for execution */
-               int                     exec_mask = UNBLOCKED_SIGNAL_QUEUE();
+               int                     i;
 
-               for (i = 0; i < PG_SIGNAL_COUNT; i++)
+               for (i = 1; i < PG_SIGNAL_COUNT; i++)
                {
                        if (exec_mask & sigmask(i))
                        {