summaryrefslogtreecommitdiff
path: root/job.c
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2013-04-27 14:20:49 +0300
committerEli Zaretskii <eliz@gnu.org>2013-04-27 14:20:49 +0300
commitda7df54309eb759837a289ade900fe8e3d6ddc36 (patch)
tree18ae26775357fc0e3dc4d9830f62cc8e561a3c2e /job.c
parentf3a4b4ce6f16830b0f2c42b14fe6f955d49eb274 (diff)
downloadgunmake-da7df54309eb759837a289ade900fe8e3d6ddc36.tar.gz
Support --output-sync on MS-Windows.
w32/compat/posixfcn.c: New file, with emulations of Posix functions and Posix functionality for MS-Windows. w32/subproc/sub_proc.c: Include io.h. (process_noinherit): New function, forces a file descriptor to not be inherited by child processes. (process_easy): Accept two additional arguments, and use them to set up the standard output and standard error handles of the child process. w32/include/sub_proc.h (process_easy): Adjust prototype. (process_noinherit): Add prototype. read.c [WINDOWS32]: Include windows.h and sub_proc.h. makeint.h (LOCALEDIR) [WINDOWS32}: Define to NULL if not defined. This is needed because the MS-Windows build doesn't have a canonical place for LOCALEDIR. (WIN32_LEAN_AND_MEAN) [WINDOWS32]: Define, to avoid getting from windows.h header too much stuff that could conflict with the code. main.c <sync_mutex>: New static variable. <switches>: Add support for "--sync-mutex" switch. (decode_output_sync_flags): Decode the --sync-mutex= switch. (prepare_mutex_handle_string) [WINDOWS32]: New function. (main): Add "output-sync" to .FEATURES. job.h (CLOSE_ON_EXEC) [WINDOWS32]: Define to call process_noinherit. (F_GETFD, F_SETLKW, F_WRLCK, F_UNLCK, struct flock) [WINDOWS32]: New macros. (RECORD_SYNC_MUTEX): New macro, a no-op for Posix platforms. (sync_handle_t): New typedef. job.c <sync_handle>: Change type to sync_handle_t. (FD_NOT_EMPTY): Seek to the file's end. Suggested by Frank Heckenbach <f.heckenbach@fh-soft.de>. (pump_from_tmp_fd) [WINDOWS32]: Switch to_fd to binary mode for the duration of this function, and then change back before returning. (start_job_command) [WINDOWS32]: Support output_sync mode on MS-Windows. Use a system-wide mutex instead of locking stdout/stderr. Call process_easy with two additional arguments: child->outfd and child->errfd. (exec_command) [WINDOWS32]: Pass two additional arguments, both -1, to process_easy, to adjust for the changed function signature. function.c (windows32_openpipe) [WINDOWS32]: This function now returns an int, which is -1 if it fails and zero otherwise. It also calls 'error' instead of 'fatal', to avoid exiting prematurely. (func_shell_base) [WINDOWS32]: Call perror_with_name if windows32_openpipe fails, now that it always returns. This avoids a compiler warning that error_prefix is not used in the MS-Windows build. config.h.W32.template (OUTPUT_SYNC): Define. build_w32.bat: Add w32/compat/posixfcn.c to compilation and linking commands. From Frank Heckenbach <f.heckenbach@fh-soft.de>: job.c (sync_output): Don't discard the output if acquire_semaphore fails; instead, dump the output unsynchronized.
Diffstat (limited to 'job.c')
-rw-r--r--job.c81
1 files changed, 71 insertions, 10 deletions
diff --git a/job.c b/job.c
index d88fc57..18494f6 100644
--- a/job.c
+++ b/job.c
@@ -246,11 +246,11 @@ unsigned int jobserver_tokens = 0;
#ifdef OUTPUT_SYNC
/* Semaphore for use in -j mode with output_sync. */
-int sync_handle = -1;
+sync_handle_t sync_handle = -1;
#define STREAM_OK(_s) ((fcntl (fileno (_s), F_GETFD) != -1) || (errno != EBADF))
-#define FD_NOT_EMPTY(_f) ((_f) >= 0 && lseek ((_f), 0, SEEK_CUR) > 0)
+#define FD_NOT_EMPTY(_f) ((_f) >= 0 && lseek ((_f), 0, SEEK_END) > 0)
#endif /* OUTPUT_SYNC */
#ifdef WINDOWS32
@@ -588,6 +588,14 @@ pump_from_tmp_fd (int from_fd, int to_fd)
ssize_t nleft, nwrite;
char buffer[8192];
+#ifdef WINDOWS32
+ int prev_mode;
+
+ /* from_fd is opened by open_tmpfd, which does it in binary mode, so
+ we need the mode of to_fd to match that. */
+ prev_mode = _setmode (to_fd, _O_BINARY);
+#endif
+
if (lseek (from_fd, 0, SEEK_SET) == -1)
perror ("lseek()");
@@ -605,13 +613,20 @@ pump_from_tmp_fd (int from_fd, int to_fd)
if (nwrite < 0)
{
perror ("write()");
- return;
+ goto finished;
}
write_buf += nwrite;
nleft -= nwrite;
}
}
+finished:
+
+#ifdef WINDOWS32
+ /* Switch to_fd back to its original mode, so that log messages by
+ Make have the same EOL format as without --output-sync. */
+ _setmode (to_fd, prev_mode);
+#endif
}
/* Support routine for sync_output() */
@@ -622,7 +637,7 @@ acquire_semaphore (void)
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
- fl.l_start = 0; /* lock just one byte according to pid */
+ fl.l_start = 0; /* lock just one byte */
fl.l_len = 1;
if (fcntl (sync_handle, F_SETLKW, &fl) != -1)
return &fl;
@@ -648,13 +663,15 @@ release_semaphore (void *sem)
static void
sync_output (struct child *c)
{
- void *sem;
-
int outfd_not_empty = FD_NOT_EMPTY (c->outfd);
int errfd_not_empty = FD_NOT_EMPTY (c->errfd);
- if ((outfd_not_empty || errfd_not_empty) && (sem = acquire_semaphore ()))
+ if (outfd_not_empty || errfd_not_empty)
{
+ /* Try to acquire the semaphore. If it fails, dump the output
+ unsynchronized; still better than silently discarding it. */
+ void *sem = acquire_semaphore ();
+
/* We've entered the "critical section" during which a lock is held.
We want to keep it as short as possible. */
if (outfd_not_empty)
@@ -667,7 +684,8 @@ sync_output (struct child *c)
pump_from_tmp_fd (c->errfd, fileno (stderr));
/* Exit the critical section. */
- release_semaphore (sem);
+ if (sem)
+ release_semaphore (sem);
}
if (c->outfd >= 0)
@@ -1723,6 +1741,42 @@ start_job_command (struct child *child)
HANDLE hPID;
char* arg0;
+#ifdef OUTPUT_SYNC
+ if (output_sync)
+ {
+ static int combined_output;
+ /* If output_sync is turned on, create a mutex to
+ synchronize on. This is done only once. */
+ if (sync_handle == -1)
+ {
+ if ((!STREAM_OK (stdout) && !STREAM_OK (stderr))
+ || (sync_handle = create_mutex ()) == -1)
+ {
+ perror_with_name ("output-sync suppressed: ", "stderr");
+ output_sync = 0;
+ }
+ else
+ {
+ combined_output = same_stream (stdout, stderr);
+ prepare_mutex_handle_string (sync_handle);
+ }
+ }
+ /* If we can synchronize, create a temporary file to hold
+ child's stdout, and another one for its stderr, if they
+ are separate. */
+ if (output_sync == OUTPUT_SYNC_MAKE
+ || (output_sync == OUTPUT_SYNC_TARGET
+ && !(flags & COMMANDS_RECURSE)))
+ {
+ if (!assign_child_tempfiles (child, combined_output))
+ {
+ perror_with_name ("output-sync suppressed: ", "stderr");
+ output_sync = 0;
+ }
+ }
+ }
+#endif /* OUTPUT_SYNC */
+
/* make UNC paths safe for CreateProcess -- backslash format */
arg0 = argv[0];
if (arg0 && arg0[0] == '/' && arg0[1] == '/')
@@ -1733,7 +1787,14 @@ start_job_command (struct child *child)
/* make sure CreateProcess() has Path it needs */
sync_Path_environment();
- hPID = process_easy(argv, child->environment);
+#ifdef OUTPUT_SYNC
+ /* Divert child output into tempfile(s) if output_sync in use. */
+ if (output_sync)
+ hPID = process_easy(argv, child->environment,
+ child->outfd, child->errfd);
+ else
+#endif
+ hPID = process_easy(argv, child->environment, -1, -1);
if (hPID != INVALID_HANDLE_VALUE)
child->pid = (pid_t) hPID;
@@ -2417,7 +2478,7 @@ exec_command (char **argv, char **envp)
sync_Path_environment();
/* launch command */
- hPID = process_easy(argv, envp);
+ hPID = process_easy(argv, envp, -1, -1);
/* make sure launch ok */
if (hPID == INVALID_HANDLE_VALUE)