Changeset 3512 for trunk/src/kmk


Ignore:
Timestamp:
Dec 16, 2021, 1:18:24 PM (4 years ago)
Author:
bird
Message:

kmk/posixos.c: Applied b552b05251980f693c729e251f93f5225b400714 from upstream: [PATCH] [SV 51159] Use a non-blocking read with pselect to avoid hangs.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/posixos.c

    r3140 r3512  
    6060}
    6161
     62static void
     63set_blocking (int fd, int blocking)
     64{
     65  // If we're not using pselect() don't change the blocking
     66#ifdef HAVE_PSELECT
     67  int flags;
     68  EINTRLOOP (flags, fcntl (fd, F_GETFL));
     69  if (flags >= 0)
     70    {
     71      int r;
     72      flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
     73      EINTRLOOP (r, fcntl (fd, F_SETFL, flags));
     74      if (r < 0)
     75        pfatal_with_name ("fcntl(O_NONBLOCK)");
     76    }
     77#endif
     78}
     79
    6280unsigned int
    6381jobserver_setup (int slots)
     
    7896        pfatal_with_name (_("init jobserver pipe"));
    7997    }
     98
     99  /* When using pselect() we want the read to be non-blocking.  */
     100  set_blocking (job_fds[0], 0);
    80101
    81102  return 1;
     
    113134      return 0;
    114135    }
     136
     137  /* When using pselect() we want the read to be non-blocking.  */
     138  set_blocking (job_fds[0], 0);
    115139
    116140  return 1;
     
    162186  unsigned int tokens = 0;
    163187
    164   /* Close the write side, so the read() won't hang.  */
     188  /* Use blocking reads to wait for all outstanding jobs.  */
     189  set_blocking (job_fds[0], 1);
     190
     191  /* Close the write side, so the read() won't hang forever.  */
    165192  close (job_fds[1]);
    166193  job_fds[1] = -1;
     
    240267jobserver_acquire (int timeout)
    241268{
    242   sigset_t empty;
    243   fd_set readfds;
    244269  struct timespec spec;
    245270  struct timespec *specp = NULL;
    246   int r;
    247   char intake;
     271  sigset_t empty;
    248272
    249273  sigemptyset (&empty);
    250 
    251   FD_ZERO (&readfds);
    252   FD_SET (job_fds[0], &readfds);
    253274
    254275  if (timeout)
     
    260281    }
    261282
    262   r = pselect (job_fds[0]+1, &readfds, NULL, NULL, specp, &empty);
    263 
    264   if (r == -1)
    265     {
    266       /* Better be SIGCHLD.  */
    267       if (errno != EINTR)
    268         pfatal_with_name (_("pselect jobs pipe"));
    269       return 0;
    270     }
    271 
    272   if (r == 0)
    273     /* Timeout.  */
    274     return 0;
    275 
    276   /* The read FD is ready: read it!  */
    277   EINTRLOOP (r, read (job_fds[0], &intake, 1));
    278   if (r < 0)
    279     pfatal_with_name (_("read jobs pipe"));
    280 
    281   /* What does it mean if read() returns 0?  It shouldn't happen because only
    282      the master make can reap all the tokens and close the write side...??  */
    283   return r > 0;
     283  while (1)
     284    {
     285      fd_set readfds;
     286      int r;
     287      char intake;
     288
     289      FD_ZERO (&readfds);
     290      FD_SET (job_fds[0], &readfds);
     291
     292      r = pselect (job_fds[0]+1, &readfds, NULL, NULL, specp, &empty);
     293      if (r < 0)
     294        switch (errno)
     295          {
     296          case EINTR:
     297            /* SIGCHLD will show up as an EINTR.  */
     298            return 0;
     299
     300          case EBADF:
     301            /* Someone closed the jobs pipe.
     302               That shouldn't happen but if it does we're done.  */
     303              O (fatal, NILF, _("job server shut down"));
     304
     305          default:
     306            pfatal_with_name (_("pselect jobs pipe"));
     307          }
     308
     309      if (r == 0)
     310        /* Timeout.  */
     311        return 0;
     312
     313      /* The read FD is ready: read it!  This is non-blocking.  */
     314      EINTRLOOP (r, read (job_fds[0], &intake, 1));
     315
     316      if (r < 0)
     317        {
     318          /* Someone sniped our token!  Try again.  */
     319          if (errno == EAGAIN)
     320            continue;
     321
     322          pfatal_with_name (_("read jobs pipe"));
     323        }
     324
     325      /* read() should never return 0: only the master make can reap all the
     326         tokens and close the write side...??  */
     327      return r > 0;
     328    }
    284329}
    285330
Note: See TracChangeset for help on using the changeset viewer.