4a787e4d01111265ade37a981e3d8ab907af49b3
[platform/upstream/make.git] / posixos.c
1 /* POSIX-based operating system interface for GNU Make.
2 Copyright (C) 2016 Free Software Foundation, Inc.
3 This file is part of GNU Make.
4
5 GNU Make is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3 of the License, or (at your option) any later
8 version.
9
10 GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along with
15 this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 #include "makeint.h"
18
19 #include <stdio.h>
20
21 #ifdef HAVE_FCNTL_H
22 # include <fcntl.h>
23 #endif
24 #if defined(HAVE_PSELECT) && defined(HAVE_SYS_SELECT_H)
25 # include <sys/select.h>
26 #endif
27
28 #include "debug.h"
29 #include "job.h"
30 #include "os.h"
31
32 #ifdef MAKE_JOBSERVER
33
34 /* This section provides OS-specific functions to support the jobserver.  */
35
36 /* These track the state of the jobserver pipe.  Passed to child instances.  */
37 static int job_fds[2] = { -1, -1 };
38
39 /* Used to signal read() that a SIGCHLD happened.  Always CLOEXEC.
40    If we use pselect() this will never be created and always -1.
41  */
42 static int job_rfd = -1;
43
44 /* Token written to the pipe (could be any character...)  */
45 static char token = '+';
46
47 static int
48 make_job_rfd (void)
49 {
50 #ifdef HAVE_PSELECT
51   /* Pretend we succeeded.  */
52   return 0;
53 #else
54   EINTRLOOP (job_rfd, dup (job_fds[0]));
55   if (job_rfd >= 0)
56     CLOSE_ON_EXEC (job_rfd);
57
58   return job_rfd;
59 #endif
60 }
61
62 unsigned int
63 jobserver_setup (int slots)
64 {
65   int r;
66
67   EINTRLOOP (r, pipe (job_fds));
68   if (r < 0)
69     pfatal_with_name (_("creating jobs pipe"));
70
71   if (make_job_rfd () < 0)
72     pfatal_with_name (_("duping jobs pipe"));
73
74   while (slots--)
75     {
76       EINTRLOOP (r, write (job_fds[1], &token, 1));
77       if (r != 1)
78         pfatal_with_name (_("init jobserver pipe"));
79     }
80
81   return 1;
82 }
83
84 unsigned int
85 jobserver_parse_auth (const char *auth)
86 {
87   /* Given the command-line parameter, parse it.  */
88   if (sscanf (auth, "%d,%d", &job_fds[0], &job_fds[1]) != 2)
89     OS (fatal, NILF,
90         _("internal error: invalid --jobserver-auth string '%s'"), auth);
91
92   DB (DB_JOBS,
93       (_("Jobserver client (fds %d,%d)\n"), job_fds[0], job_fds[1]));
94
95 #ifdef HAVE_FCNTL_H
96 # define FD_OK(_f) (fcntl ((_f), F_GETFD) != -1)
97 #else
98 # define FD_OK(_f) 1
99 #endif
100
101   /* Make sure our pipeline is valid, and (possibly) create a duplicate pipe,
102      that will be closed in the SIGCHLD handler.  If this fails with EBADF,
103      the parent has closed the pipe on us because it didn't think we were a
104      submake.  If so, warn and default to -j1.  */
105
106   if (!FD_OK (job_fds[0]) || !FD_OK (job_fds[1]) || make_job_rfd () < 0)
107     {
108       if (errno != EBADF)
109         pfatal_with_name (_("jobserver pipeline"));
110
111       job_fds[0] = job_fds[1] = -1;
112
113       return 0;
114     }
115
116   return 1;
117 }
118
119 char *
120 jobserver_get_auth (void)
121 {
122   char *auth = xmalloc ((INTSTR_LENGTH * 2) + 2);
123   sprintf (auth, "%d,%d", job_fds[0], job_fds[1]);
124   return auth;
125 }
126
127 unsigned int
128 jobserver_enabled (void)
129 {
130   return job_fds[0] >= 0;
131 }
132
133 void
134 jobserver_clear (void)
135 {
136   if (job_fds[0] >= 0)
137     close (job_fds[0]);
138   if (job_fds[1] >= 0)
139     close (job_fds[1]);
140   if (job_rfd >= 0)
141     close (job_rfd);
142
143   job_fds[0] = job_fds[1] = job_rfd = -1;
144 }
145
146 void
147 jobserver_release (int is_fatal)
148 {
149   int r;
150   EINTRLOOP (r, write (job_fds[1], &token, 1));
151   if (r != 1)
152     {
153       if (is_fatal)
154         pfatal_with_name (_("write jobserver"));
155       perror_with_name ("write", "");
156     }
157 }
158
159 unsigned int
160 jobserver_acquire_all (void)
161 {
162   unsigned int tokens = 0;
163
164   /* Close the write side, so the read() won't hang.  */
165   close (job_fds[1]);
166   job_fds[1] = -1;
167
168   while (1)
169     {
170       char intake;
171       int r;
172       EINTRLOOP (r, read (job_fds[0], &intake, 1));
173       if (r != 1)
174         return tokens;
175       ++tokens;
176     }
177 }
178
179 /* Prepare the jobserver to start a child process.  */
180 void
181 jobserver_pre_child (int recursive)
182 {
183   /* If it's not a recursive make, avoid polutting the jobserver pipes.  */
184   if (!recursive && job_fds[0] >= 0)
185     {
186       CLOSE_ON_EXEC (job_fds[0]);
187       CLOSE_ON_EXEC (job_fds[1]);
188     }
189 }
190
191 void
192 jobserver_post_child (int recursive)
193 {
194 #if defined(F_GETFD) && defined(F_SETFD)
195   if (!recursive && job_fds[0] >= 0)
196     {
197       unsigned int i;
198       for (i = 0; i < 2; ++i)
199         {
200           int flags;
201           EINTRLOOP (flags, fcntl (job_fds[i], F_GETFD));
202           if (flags >= 0)
203             {
204               int r;
205               EINTRLOOP (r, fcntl (job_fds[i], F_SETFD, flags & ~FD_CLOEXEC));
206             }
207         }
208     }
209 #endif
210 }
211
212 void
213 jobserver_signal (void)
214 {
215   if (job_rfd >= 0)
216     {
217       close (job_rfd);
218       job_rfd = -1;
219     }
220 }
221
222 void
223 jobserver_pre_acquire (void)
224 {
225   /* Make sure we have a dup'd FD.  */
226   if (job_rfd < 0 && job_fds[0] >= 0 && make_job_rfd () < 0)
227     pfatal_with_name (_("duping jobs pipe"));
228 }
229
230 #ifdef HAVE_PSELECT
231
232 /* Use pselect() to atomically wait for both a signal and a file descriptor.
233    It also provides a timeout facility so we don't need to use SIGALRM.
234
235    This method relies on the fact that SIGCHLD will be blocked everywhere,
236    and only unblocked (atomically) within the pselect() call, so we can
237    never miss a SIGCHLD.
238  */
239 unsigned int
240 jobserver_acquire (int timeout)
241 {
242   sigset_t empty;
243   fd_set readfds;
244   struct timespec spec;
245   struct timespec *specp = NULL;
246   int r;
247   char intake;
248
249   sigemptyset (&empty);
250
251   FD_ZERO (&readfds);
252   FD_SET (job_fds[0], &readfds);
253
254   if (timeout)
255     {
256       /* Alarm after one second (is this too granular?)  */
257       spec.tv_sec = 1;
258       spec.tv_nsec = 0;
259       specp = &spec;
260     }
261
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;
284 }
285
286 #else
287
288 /* This method uses a "traditional" UNIX model for waiting on both a signal
289    and a file descriptor.  However, it's complex and since we have a SIGCHLD
290    handler installed we need to check ALL system calls for EINTR: painful!
291
292    Read a token.  As long as there's no token available we'll block.  We
293    enable interruptible system calls before the read(2) so that if we get a
294    SIGCHLD while we're waiting, we'll return with EINTR and we can process the
295    death(s) and return tokens to the free pool.
296
297    Once we return from the read, we immediately reinstate restartable system
298    calls.  This allows us to not worry about checking for EINTR on all the
299    other system calls in the program.
300
301    There is one other twist: there is a span between the time reap_children()
302    does its last check for dead children and the time the read(2) call is
303    entered, below, where if a child dies we won't notice.  This is extremely
304    serious as it could cause us to deadlock, given the right set of events.
305
306    To avoid this, we do the following: before we reap_children(), we dup(2)
307    the read FD on the jobserver pipe.  The read(2) call below uses that new
308    FD.  In the signal handler, we close that FD.  That way, if a child dies
309    during the section mentioned above, the read(2) will be invoked with an
310    invalid FD and will return immediately with EBADF.  */
311
312 static RETSIGTYPE
313 job_noop (int sig UNUSED)
314 {
315 }
316
317 /* Set the child handler action flags to FLAGS.  */
318 static void
319 set_child_handler_action_flags (int set_handler, int set_alarm)
320 {
321   struct sigaction sa;
322
323 #ifdef __EMX__
324   /* The child handler must be turned off here.  */
325   signal (SIGCHLD, SIG_DFL);
326 #endif
327
328   memset (&sa, '\0', sizeof sa);
329   sa.sa_handler = child_handler;
330   sa.sa_flags = set_handler ? 0 : SA_RESTART;
331
332 #if defined SIGCHLD
333   if (sigaction (SIGCHLD, &sa, NULL) < 0)
334     pfatal_with_name ("sigaction: SIGCHLD");
335 #endif
336
337 #if defined SIGCLD && SIGCLD != SIGCHLD
338   if (sigaction (SIGCLD, &sa, NULL) < 0)
339     pfatal_with_name ("sigaction: SIGCLD");
340 #endif
341
342 #if defined SIGALRM
343   if (set_alarm)
344     {
345       /* If we're about to enter the read(), set an alarm to wake up in a
346          second so we can check if the load has dropped and we can start more
347          work.  On the way out, turn off the alarm and set SIG_DFL.  */
348       if (set_handler)
349         {
350           sa.sa_handler = job_noop;
351           sa.sa_flags = 0;
352           if (sigaction (SIGALRM, &sa, NULL) < 0)
353             pfatal_with_name ("sigaction: SIGALRM");
354           alarm (1);
355         }
356       else
357         {
358           alarm (0);
359           sa.sa_handler = SIG_DFL;
360           sa.sa_flags = 0;
361           if (sigaction (SIGALRM, &sa, NULL) < 0)
362             pfatal_with_name ("sigaction: SIGALRM");
363         }
364     }
365 #endif
366 }
367
368 unsigned int
369 jobserver_acquire (int timeout)
370 {
371   char intake;
372   int got_token;
373   int saved_errno;
374
375   /* Set interruptible system calls, and read() for a job token.  */
376   set_child_handler_action_flags (1, timeout);
377
378   EINTRLOOP (got_token, read (job_rfd, &intake, 1));
379   saved_errno = errno;
380
381   set_child_handler_action_flags (0, timeout);
382
383   if (got_token == 1)
384     return 1;
385
386   /* If the error _wasn't_ expected (EINTR or EBADF), fatal.  Otherwise,
387      go back and reap_children(), and try again.  */
388   errno = saved_errno;
389
390   if (errno != EINTR && errno != EBADF)
391     pfatal_with_name (_("read jobs pipe"));
392
393   if (errno == EBADF)
394     DB (DB_JOBS, ("Read returned EBADF.\n"));
395
396   return 0;
397 }
398
399 #endif
400
401 #endif /* MAKE_JOBSERVER */
402
403 /* Create a "bad" file descriptor for stdin when parallel jobs are run.  */
404 int
405 get_bad_stdin (void)
406 {
407   static int bad_stdin = -1;
408
409   /* Set up a bad standard input that reads from a broken pipe.  */
410
411   if (bad_stdin == -1)
412     {
413       /* Make a file descriptor that is the read end of a broken pipe.
414          This will be used for some children's standard inputs.  */
415       int pd[2];
416       if (pipe (pd) == 0)
417         {
418           /* Close the write side.  */
419           (void) close (pd[1]);
420           /* Save the read side.  */
421           bad_stdin = pd[0];
422
423           /* Set the descriptor to close on exec, so it does not litter any
424              child's descriptor table.  When it is dup2'd onto descriptor 0,
425              that descriptor will not close on exec.  */
426           CLOSE_ON_EXEC (bad_stdin);
427         }
428     }
429
430   return bad_stdin;
431 }