1 /* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*-
2 *
3 * distcc -- A simple distributed compiler system
4 *
5 * Copyright (C) 2002, 2003, 2004 by Martin Pool <mbp@samba.org>
6 * Copyright 2007 Google Inc.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 * USA.
22 */
23
24
25 /* 18 Their bows also shall dash the young men
26 * to pieces; and they shall have no pity on
27 * the fruit of the womb; their eyes shall not
28 * spare children.
29 * -- Isaiah 13 */
30
31 /**
32 * @file
33 *
34 * Run compilers or preprocessors.
35 *
36 * The whole server is run in a separate process group and normally in a
37 * separate session. (It is not a separate session in --no-detach debug
38 * mode.) This allows us to cleanly kill off all children and all compilers
39 * when the parent is terminated.
40 *
41 * @todo On Cygwin, fork() must be emulated and therefore will be
42 * slow. It would be faster to just use their spawn() call, rather
43 * than fork/exec.
44 **/
45
46 #include <config.h>
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <unistd.h>
51 #include <string.h>
52 #include <fcntl.h>
53 #include <errno.h>
54 #include <poll.h>
55 #include <signal.h>
56
57 #include <sys/types.h>
58 #include <sys/wait.h>
59 #include <sys/stat.h>
60 #include <sys/time.h>
61 #include <sys/resource.h>
62
63 #ifdef __CYGWIN__
64 /* #define NOGDI */
65 #define RC_INVOKED
66 #define NOWINRES
67 #include <windows.h>
68 #endif
69
70 #include "distcc.h"
71 #include "trace.h"
72 #include "util.h"
73 #include "exitcode.h"
74 #include "exec.h"
75 #include "lock.h"
76 #include "hosts.h"
77 #include "dopt.h"
78
79 const int timeout_null_fd = -1;
80 int dcc_job_lifetime = 0;
81
82 static void dcc_inside_child(char **argv,
83 const char *stdin_file,
84 const char *stdout_file,
85 const char *stderr_file) NORETURN;
86
87
88 static void dcc_execvp(char **argv) NORETURN;
89
dcc_note_execution(struct dcc_hostdef * host,char ** argv)90 void dcc_note_execution(struct dcc_hostdef *host, char **argv)
91 {
92 char *astr;
93
94 astr = dcc_argv_tostr(argv);
95 rs_log(RS_LOG_INFO|RS_LOG_NONAME, "exec on %s: %s",
96 host->hostdef_string, astr);
97 free(astr);
98 }
99
100
101 /**
102 * Redirect stdin/out/err. Filenames may be NULL to leave them untouched.
103 *
104 * This is called when running a job remotely, but *not* when running
105 * it locally, because people might e.g. want cpp to read from stdin.
106 **/
dcc_redirect_fds(const char * stdin_file,const char * stdout_file,const char * stderr_file)107 int dcc_redirect_fds(const char *stdin_file,
108 const char *stdout_file,
109 const char *stderr_file)
110 {
111 int ret;
112
113 if (stdin_file)
114 if ((ret = dcc_redirect_fd(STDIN_FILENO, stdin_file, O_RDONLY)))
115 return ret;
116
117 if (stdout_file) {
118 if ((ret = dcc_redirect_fd(STDOUT_FILENO, stdout_file,
119 O_WRONLY | O_CREAT | O_TRUNC)))
120 return ret;
121 }
122
123 if (stderr_file) {
124 /* Open in append mode, because the server will dump its own error
125 * messages into the compiler's error file. */
126 if ((ret = dcc_redirect_fd(STDERR_FILENO, stderr_file,
127 O_WRONLY | O_CREAT | O_APPEND)))
128 return ret;
129 }
130
131 return 0;
132 }
133
134
135 #ifdef __CYGWIN__
136 /* Execute a process WITHOUT console window and correctly redirect output. */
dcc_execvp_cyg(char ** argv,const char * input_file,const char * output_file,const char * error_file)137 static DWORD dcc_execvp_cyg(char **argv, const char *input_file,
138 const char *output_file, const char *error_file)
139 {
140 STARTUPINFO m_siStartInfo;
141 PROCESS_INFORMATION m_piProcInfo;
142 char cmdline[MAX_PATH+1]={0};
143 HANDLE stdin_hndl=INVALID_HANDLE_VALUE;
144 HANDLE stdout_hndl=INVALID_HANDLE_VALUE;
145 HANDLE stderr_hndl=INVALID_HANDLE_VALUE;
146 char **ptr;
147 DWORD exit_code;
148 BOOL bRet=0;
149
150 ZeroMemory(&m_siStartInfo, sizeof(STARTUPINFO));
151 ZeroMemory( &m_piProcInfo, sizeof(PROCESS_INFORMATION) );
152
153 /* Open files for IO redirection */
154 if (input_file && strcmp(input_file,"/dev/null")!=0)
155 {
156 if ((stdin_hndl = CreateFile(input_file,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_ALWAYS,
157 FILE_ATTRIBUTE_TEMPORARY,NULL)) == INVALID_HANDLE_VALUE) {
158 exit_code = GetLastError();
159 goto cleanup;
160 }
161 } else
162 stdin_hndl = GetStdHandle(STD_INPUT_HANDLE);
163
164 if (output_file && strcmp(output_file,"/dev/null")!=0)
165 {
166 if ((stdout_hndl = CreateFile(output_file,GENERIC_WRITE,FILE_SHARE_READ,NULL,
167 CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY,NULL)) == INVALID_HANDLE_VALUE) {
168 exit_code = GetLastError();
169 goto cleanup;
170 }
171 } else
172 stdout_hndl = GetStdHandle(STD_OUTPUT_HANDLE);
173
174 if (error_file && strcmp(error_file,"/dev/null")!=0)
175 {
176 if ((stderr_hndl = CreateFile(error_file, GENERIC_WRITE,
177 FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,
178 OPEN_ALWAYS, FILE_ATTRIBUTE_TEMPORARY,NULL)) == INVALID_HANDLE_VALUE) {
179 exit_code = GetLastError();
180 goto cleanup;
181 }
182 /* Seek to the end of file (ignore return code) */
183 SetFilePointer(stderr_hndl,0,NULL,FILE_END);
184
185 } else
186 stderr_hndl = GetStdHandle(STD_ERROR_HANDLE);
187
188 /* Ensure handles can be inherited */
189 SetHandleInformation(stdin_hndl,HANDLE_FLAG_INHERIT,HANDLE_FLAG_INHERIT);
190 SetHandleInformation(stdout_hndl,HANDLE_FLAG_INHERIT,HANDLE_FLAG_INHERIT);
191 SetHandleInformation(stderr_hndl,HANDLE_FLAG_INHERIT,HANDLE_FLAG_INHERIT);
192
193 /*Set up members of STARTUPINFO structure.*/
194 m_siStartInfo.cb = sizeof(STARTUPINFO);
195 m_siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
196 m_siStartInfo.wShowWindow = SW_HIDE;
197 m_siStartInfo.hStdInput = stdin_hndl;
198 m_siStartInfo.hStdOutput = stdout_hndl;
199 m_siStartInfo.hStdError = stderr_hndl;
200
201 /* Create command line */
202 for (ptr=argv;*ptr!=NULL;ptr++)
203 {
204 strcat(cmdline, *ptr);
205 strcat(cmdline, " ");
206 }
207
208 /* Create the child process. */
209 bRet = CreateProcess(NULL,
210 cmdline, /* application name */
211 NULL, /* process security attributes */
212 NULL, /* primary thread security attributes */
213 TRUE, /* handles are inherited */
214 CREATE_NEW_CONSOLE, /* creation flags */
215 NULL, /* use parent's environment */
216 NULL, /* use parent's current directory */
217 &m_siStartInfo, /* STARTUPINFO pointer */
218 &m_piProcInfo); /* receives PROCESS_INFORMATION */
219 if (!bRet) {
220 exit_code = GetLastError();
221 goto cleanup;
222 }
223
224 WaitForSingleObject(m_piProcInfo.hProcess, (DWORD)(-1L));
225 /* return termination code and exit code*/
226 GetExitCodeProcess(m_piProcInfo.hProcess, &exit_code);
227 CloseHandle(m_piProcInfo.hProcess);
228
229 /* We can get here only if process creation failed */
230 cleanup:
231 if (stdin_hndl != INVALID_HANDLE_VALUE) CloseHandle(stdin_hndl);
232 if (stdout_hndl != INVALID_HANDLE_VALUE) CloseHandle(stdout_hndl);
233 if (stderr_hndl != INVALID_HANDLE_VALUE) CloseHandle(stderr_hndl);
234
235 if (bRet)
236 ExitProcess(exit_code); /* Return cmdline's exit-code to parent process */
237 else
238 return exit_code; /* Return failure reason to calling fn */
239 }
240 #endif
241
242 /**
243 * Replace this program with another in the same process.
244 *
245 * Does not return, either execs the compiler in place, or exits with
246 * a message.
247 **/
dcc_execvp(char ** argv)248 static void dcc_execvp(char **argv)
249 {
250 char *slash;
251
252 execvp(argv[0], argv);
253
254 /* If we're still running, the program was not found on the path. One
255 * thing that might have happened here is that the client sent an absolute
256 * compiler path, but the compiler's located somewhere else on the server.
257 * In the absence of anything better to do, we search the path for its
258 * basename.
259 *
260 * Actually this code is called on both the client and server, which might
261 * cause unintnded behaviour in contrived cases, like giving a full path
262 * to a file that doesn't exist. I don't think that's a problem. */
263
264 slash = strrchr(argv[0], '/');
265 if (slash)
266 execvp(slash + 1, argv);
267
268 /* shouldn't be reached */
269 rs_log_error("failed to exec %s: %s", argv[0], strerror(errno));
270
271 dcc_exit(EXIT_COMPILER_MISSING); /* a generalization, i know */
272 }
273
274
275
276 /**
277 * Called inside the newly-spawned child process to execute a command.
278 * Either executes it, or returns an appropriate error.
279 *
280 * This routine also takes a lock on localhost so that it's counted
281 * against the process load. That lock will go away when the process
282 * exits.
283 *
284 * In this current version locks are taken without regard to load limitation
285 * on the current machine. The main impact of this is that cpp running on
286 * localhost will cause jobs to be preferentially distributed away from
287 * localhost, but it should never cause the machine to deadlock waiting for
288 * localhost slots.
289 *
290 * @param what Type of process to be run here (cpp, cc, ...)
291 **/
dcc_inside_child(char ** argv,const char * stdin_file,const char * stdout_file,const char * stderr_file)292 static void dcc_inside_child(char **argv,
293 const char *stdin_file,
294 const char *stdout_file,
295 const char *stderr_file)
296 {
297 int ret;
298
299 if ((ret = dcc_ignore_sigpipe(0)))
300 goto fail; /* set handler back to default */
301
302 /* Ignore failure */
303 dcc_increment_safeguard();
304
305 #ifdef __CYGWIN__
306 /* This will execute compiler and CORRECTLY redirect output if compiler is
307 * a native Windows application. If this never returns, it means the
308 * compiler-execute succeeded. We use a hack to decide if it's a windows
309 * application: if argv[0] starts with "<letter>:" or with "\\", then it's
310 * a windows path and we try dcc_execvp_cyg. If not, we assume it's a
311 * cygwin app and fall through to the unix-style forking, below. If we
312 * guess wrong, dcc_execvp_cyg will probably fail with error 3
313 * (windows-exe for "path not found"), so again we'll fall through to the
314 * unix-fork case. Otherwise we just fail in a generic way.
315 * TODO(csilvers): Figure out the right way to deal with this. Running
316 * cygwin apps via dcc_execvp_cyg segfaults (and takes a
317 * long time to do it too), so I want to avoid that if
318 * possible. I don't know enough about cygwin or
319 * cygwin/windows interactions to know the right thing to
320 * do here. Until distcc has cl.exe support, this may
321 * all be a moot point anyway.
322 */
323 if (argv[0] && ((argv[0][0] != '\0' && argv[0][1] == ':') ||
324 (argv[0][0] == '\\' && argv[0][1] == '\\'))) {
325 DWORD status;
326 status = dcc_execvp_cyg(argv, stdin_file, stdout_file, stderr_file);
327 if (status != 3) {
328 ret = EXIT_DISTCC_FAILED;
329 goto fail;
330 }
331 }
332 #endif
333
334 /* do this last, so that any errors from previous operations are
335 * visible */
336 if ((ret = dcc_redirect_fds(stdin_file, stdout_file, stderr_file)))
337 goto fail;
338
339 dcc_execvp(argv);
340
341 ret = EXIT_DISTCC_FAILED;
342
343 fail:
344 dcc_exit(ret);
345 }
346
347
dcc_new_pgrp(void)348 int dcc_new_pgrp(void)
349 {
350 /* If we're a session group leader, then we are not able to call
351 * setpgid(). However, setsid will implicitly have put us into a new
352 * process group, so we don't have to do anything. */
353
354 /* Does everyone have getpgrp()? It's in POSIX.1. We used to call
355 * getpgid(0), but that is not available on BSD/OS. */
356 if (getpgrp() == getpid()) {
357 rs_trace("already a process group leader");
358 return 0;
359 }
360
361 if (setpgid(0, 0) == 0) {
362 rs_trace("entered process group");
363 return 0;
364 } else {
365 rs_trace("setpgid(0, 0) failed: %s", strerror(errno));
366 return EXIT_DISTCC_FAILED;
367 }
368 }
369
370
371 /**
372 * Run @p argv in a child asynchronously.
373 *
374 * stdin, stdout and stderr are redirected as shown, unless those
375 * filenames are NULL. In that case they are left alone.
376 *
377 * @warning When called on the daemon, where stdin/stdout may refer to random
378 * network sockets, all of the standard file descriptors must be redirected!
379 **/
dcc_spawn_child(char ** argv,pid_t * pidptr,const char * stdin_file,const char * stdout_file,const char * stderr_file)380 int dcc_spawn_child(char **argv, pid_t *pidptr,
381 const char *stdin_file,
382 const char *stdout_file,
383 const char *stderr_file)
384 {
385 pid_t pid;
386
387 dcc_trace_argv("forking to execute", argv);
388
389 pid = fork();
390 if (pid == -1) {
391 rs_log_error("failed to fork: %s", strerror(errno));
392 return EXIT_OUT_OF_MEMORY; /* probably */
393 } else if (pid == 0) {
394 /* If this is a remote compile,
395 * put the child in a new group, so we can
396 * kill it and all its descendents without killing distccd
397 * FIXME: if you kill distccd while it's compiling, and
398 * the compiler has an infinite loop bug, the new group
399 * will run forever until you kill it.
400 */
401 if (stdout_file != NULL) {
402 if (dcc_new_pgrp() != 0)
403 rs_trace("Unable to start a new group\n");
404 }
405 dcc_inside_child(argv, stdin_file, stdout_file, stderr_file);
406 /* !! NEVER RETURN FROM HERE !! */
407 } else {
408 *pidptr = pid;
409 rs_trace("child started as pid%d", (int) pid);
410 return 0;
411 }
412 }
413
414
dcc_reset_signal(int whichsig)415 void dcc_reset_signal(int whichsig)
416 {
417 struct sigaction act_dfl;
418
419 memset(&act_dfl, 0, sizeof act_dfl);
420 act_dfl.sa_handler = SIG_DFL;
421 sigaction(whichsig, &act_dfl, NULL);
422 /* might be called from signal handler, therefore no IO to log a
423 * message */
424 }
425
426
sys_wait4(pid_t pid,int * status,int options,struct rusage * rusage)427 static int sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage)
428 {
429
430 /* Prefer use waitpid to wait4 for non-blocking wait with WNOHANG option */
431 #ifdef HAVE_WAITPID
432 /* Just doing getrusage(children) is not sufficient, because other
433 * children may have exited previously. */
434 memset(rusage, 0, sizeof *rusage);
435 return waitpid(pid, status, options);
436 #elif HAVE_WAIT4
437 return wait4(pid, status, options, rusage);
438 #else
439 #error Please port this
440 #endif
441 }
442
443
444 /**
445 * Blocking wait for a child to exit. This is used when waiting for
446 * cpp, gcc, etc.
447 *
448 * This is not used by the daemon-parent; it has its own
449 * implementation in dcc_reap_kids(). They could be unified, but the
450 * parent only waits when it thinks a child has exited; the child
451 * waits all the time.
452 **/
dcc_collect_child(const char * what,pid_t pid,int * wait_status,int in_fd)453 int dcc_collect_child(const char *what, pid_t pid,
454 int *wait_status, int in_fd)
455 {
456 struct rusage ru;
457 pid_t ret_pid;
458
459 int ret;
460 int wait_timeout_sec;
461 fd_set fds,readfds;
462
463 wait_timeout_sec = dcc_job_lifetime;
464
465 FD_ZERO(&readfds);
466 if (in_fd != timeout_null_fd){
467 FD_SET(in_fd,&readfds);
468 }
469
470
471 while (!dcc_job_lifetime || wait_timeout_sec-- >= 0) {
472
473 /* If we're called with a socket, break out of the loop if the socket
474 * disconnects. To do that, we need to block in select, not in
475 * sys_wait4. (Only waitpid uses WNOHANG to mean don't block ever,
476 * so I've modified sys_wait4 above to preferentially call waitpid.)
477 */
478 int flags = (in_fd == timeout_null_fd) ? 0 : WNOHANG;
479 ret_pid = sys_wait4(pid, wait_status, flags, &ru);
480
481 if (ret_pid == -1) {
482 if (errno == EINTR) {
483 rs_trace("wait4 was interrupted; retrying");
484 } else {
485 rs_log_error("sys_wait4(pid=%d) borked: %s", (int) pid,
486 strerror(errno));
487 return EXIT_DISTCC_FAILED;
488 }
489 } else if (ret_pid != 0) {
490 /* This is not the main user-visible message; that comes from
491 * critique_status(). */
492 rs_trace("%s child %ld terminated with status %#x",
493 what, (long) ret_pid, *wait_status);
494 rs_log_info("%s times: user %lld.%06lds, system %lld.%06lds, "
495 "%ld minflt, %ld majflt",
496 what,
497 (long long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec,
498 (long long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec,
499 ru.ru_minflt, ru.ru_majflt);
500
501 return 0;
502 }
503
504 /* check timeout */
505 if (in_fd != timeout_null_fd) {
506 struct timeval timeout;
507
508 /* If client disconnects, the socket will become readable,
509 * and a read should return -1 and set errno to EPIPE.
510 */
511 fds = readfds;
512 timeout.tv_sec = 1;
513 timeout.tv_usec = 0;
514 ret = select(in_fd+1,&fds,NULL,NULL,&timeout);
515 if (ret == 1) {
516 char buf;
517 int nread = read(in_fd, &buf, 1);
518 if ((nread == -1) && (errno == EWOULDBLOCK)) {
519 /* spurious wakeup, ignore */
520 ;
521 } else if (nread == 0) {
522 rs_log_error("Client fd disconnected, killing job");
523 /* If killpg fails, it might means the child process is not
524 * in a new group, so, just kill the child process */
525 if (killpg(pid,SIGTERM)!=0)
526 kill(pid, SIGTERM);
527 return EXIT_IO_ERROR;
528 } else if (nread == 1) {
529 rs_log_error("Bug! Read from fd succeeded when checking "
530 "whether client disconnected!");
531 } else {
532 rs_log_error("Bug! nread %d, errno %d checking whether "
533 "client disconnected!", nread, errno);
534 }
535 }
536 } else {
537 poll(NULL, 0, 1000);
538 }
539 }
540 /* If timeout, also kill the child process */
541 if (killpg(pid, SIGTERM) != 0)
542 kill(pid, SIGTERM);
543 rs_log_error("Compilation takes too long, timeout.");
544
545 return EXIT_TIMEOUT;
546 }
547
548
549
550 /**
551 * Analyze and report to the user on a command's exit code.
552 *
553 * @param command short human-readable description of the command (perhaps
554 * argv[0])
555 *
556 * @returns 0 if the command succeeded; 128+SIGNAL if it stopped on a
557 * signal; otherwise the command's exit code.
558 **/
dcc_critique_status(int status,const char * command,const char * input_fname,struct dcc_hostdef * host,int verbose)559 int dcc_critique_status(int status,
560 const char *command,
561 const char *input_fname,
562 struct dcc_hostdef *host,
563 int verbose)
564 {
565 int logmode;
566
567 /* verbose mode is only used for executions that the user is likely to
568 * particularly need to know about */
569 if (verbose)
570 logmode = RS_LOG_ERR | RS_LOG_NONAME;
571 else
572 logmode = RS_LOG_INFO | RS_LOG_NONAME;
573
574 if (input_fname == NULL)
575 input_fname = "(null)";
576
577 if (WIFSIGNALED(status)) {
578 #ifdef HAVE_STRSIGNAL
579 rs_log(logmode,
580 "%s %s on %s: %s%s",
581 command, input_fname, host->hostdef_string,
582 strsignal(WTERMSIG(status)),
583 WCOREDUMP(status) ? " (core dumped)" : "");
584 #else
585 rs_log(logmode,
586 "%s %s on %s terminated by signal %d%s",
587 command, input_fname, host->hostdef_string,
588 WTERMSIG(status),
589 WCOREDUMP(status) ? " (core dumped)" : "");
590 #endif
591 /* Unix convention is to return 128+signal when a subprocess crashes. */
592 return 128 + WTERMSIG(status);
593 } else if (WEXITSTATUS(status) == 1) {
594 /* Normal failure gives exit code 1, so handle that specially */
595 rs_log(logmode, "%s %s on %s failed", command, input_fname, host->hostdef_string);
596 return WEXITSTATUS(status);
597 } else if (WEXITSTATUS(status)) {
598 /* This is a tough call; we don't really want to clutter the client's
599 * error stream, but if we don't say where the compilation failed then
600 * people may find it hard to work things out. */
601
602 rs_log(logmode,
603 "%s %s on %s failed with exit code %d",
604 command, input_fname, host->hostdef_string, WEXITSTATUS(status));
605 return WEXITSTATUS(status);
606 } else {
607 rs_log(RS_LOG_INFO|RS_LOG_NONAME,
608 "%s %s on %s completed ok", command, input_fname, host->hostdef_string);
609 return 0;
610 }
611 }
612