]> granicus.if.org Git - postgresql/commitdiff
Fix busy-wait in pgbench, with --rate.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Sun, 1 Oct 2017 06:29:27 +0000 (09:29 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Sun, 1 Oct 2017 06:34:29 +0000 (09:34 +0300)
If --rate was used to throttle pgbench, it failed to sleep when it had
nothing to do, leading to a busy-wait with 100% CPU usage. This bug was
introduced in the refactoring in v10. Before that, sleep() was called with
a timeout, even when there were no file descriptors to wait for.

Reported by Jeff Janes, patch by Fabien COELHO. Backpatch to v10.

Discussion: https://www.postgresql.org/message-id/CAMkU%3D1x5hoX0pLLKPRnXCy0T8uHoDvXdq%2B7kAM9eoC9_z72ucw%40mail.gmail.com

src/bin/pgbench/pgbench.c

index 58fdc477eee26911553b93cf360203a18a00596c..2bdfc89d2a52d878fe88dc81e1486f43394b8239 100644 (file)
@@ -4539,20 +4539,30 @@ threadRun(void *arg)
                 * or it's time to print a progress report.  Update input_mask to show
                 * which client(s) received data.
                 */
-               if (min_usec > 0 && maxsock != -1)
+               if (min_usec > 0)
                {
-                       int                     nsocks; /* return from select(2) */
+                       int                     nsocks = 0; /* return from select(2) if called */
 
                        if (min_usec != PG_INT64_MAX)
                        {
-                               struct timeval timeout;
+                               if (maxsock != -1)
+                               {
+                                       struct timeval timeout;
 
-                               timeout.tv_sec = min_usec / 1000000;
-                               timeout.tv_usec = min_usec % 1000000;
-                               nsocks = select(maxsock + 1, &input_mask, NULL, NULL, &timeout);
+                                       timeout.tv_sec = min_usec / 1000000;
+                                       timeout.tv_usec = min_usec % 1000000;
+                                       nsocks = select(maxsock + 1, &input_mask, NULL, NULL, &timeout);
+                               }
+                               else /* nothing active, simple sleep */
+                               {
+                                       pg_usleep(min_usec);
+                               }
                        }
-                       else
+                       else /* no explicit delay, select without timeout */
+                       {
                                nsocks = select(maxsock + 1, &input_mask, NULL, NULL, NULL);
+                       }
+
                        if (nsocks < 0)
                        {
                                if (errno == EINTR)
@@ -4565,7 +4575,7 @@ threadRun(void *arg)
                                goto done;
                        }
                }
-               else
+               else /* min_usec == 0, i.e. something needs to be executed */
                {
                        /* If we didn't call select(), don't try to read any data */
                        FD_ZERO(&input_mask);