blob: 4c8d47db64e87d3777a8db3872beb96a3bce822c [file] [log] [blame]
=== modified file 'init/job_process.c'
--- init/job_process.c 2011-03-22 17:46:46 +0000
+++ init/job_process.c 2011-05-12 19:21:16 +0000
@@ -145,7 +145,8 @@
nih_local char *script = NULL;
char **e;
size_t argc, envc;
- int error = FALSE, fds[2], trace = FALSE, shell = FALSE;
+ int fds[2] = { -1, -1 };
+ int error = FALSE, trace = FALSE, shell = FALSE;
nih_assert (job != NULL);
@@ -208,12 +209,9 @@
shell = TRUE;
- /* FIXME actually always want it to be /proc/self/fd/3 and
- * dup2() in the child to make it that way ... no way
- * of passing that yet
- */
cmd = NIH_MUST (nih_sprintf (argv, "%s/%d",
- "/proc/self/fd", fds[0]));
+ "/proc/self/fd",
+ JOB_PROCESS_SCRIPT_FD));
NIH_MUST (nih_str_array_addp (&argv, NULL,
&argc, cmd));
}
@@ -259,7 +257,7 @@
/* Spawn the process, repeat until fork() works */
while ((job->pid[process] = job_process_spawn (job->class, argv,
- env, trace)) < 0) {
+ env, trace, fds[0])) < 0) {
NihError *err;
err = nih_error_get ();
@@ -321,7 +319,8 @@
* a path. Instruct the shell to close this extra fd and
* not to leak it.
*/
- NIH_ZERO (nih_io_printf (io, "exec %d<&-\n", fds[0]));
+ NIH_ZERO (nih_io_printf (io, "exec %d<&-\n",
+ JOB_PROCESS_SCRIPT_FD));
NIH_ZERO (nih_io_write (io, script, strlen (script)));
nih_io_shutdown (io);
@@ -336,7 +335,8 @@
* @class: job class of process to be spawned,
* @argv: NULL-terminated list of arguments for the process,
* @env: NULL-terminated list of environment variables for the process,
- * @trace: whether to trace this process.
+ * @trace: whether to trace this process,
+ * @script_fd: script file descriptor.
*
* This function spawns a new process using the @class details to set up the
* environment for it; the process is always a session and process group
@@ -352,6 +352,9 @@
* wait for this and then may use it to set options before continuing the
* process.
*
+ * If @script_fd is not -1, this file descriptor is dup()d to the special fd 9
+ * (moving any other out of the way if necessary).
+ *
* This function only spawns the process, it is up to the caller to ensure
* that the information is saved into the job and that the process is watched,
* etc.
@@ -367,7 +370,8 @@
job_process_spawn (JobClass *class,
char * const argv[],
char * const *env,
- int trace)
+ int trace,
+ int script_fd)
{
sigset_t child_set, orig_set;
pid_t pid;
@@ -433,8 +437,26 @@
* far because read() returned zero.
*/
close (fds[0]);
+ if (fds[1] == JOB_PROCESS_SCRIPT_FD) {
+ int tmp = dup2 (fds[1], fds[0]);
+ if (tmp < 0)
+ job_process_error_abort (fds[1], JOB_PROCESS_ERROR_DUP, 0);
+ close (fds[1]);
+ fds[1] = tmp;
+ }
nih_io_set_cloexec (fds[1]);
+ /* Move the script fd to special fd 9; the only gotcha is if that
+ * would be our error descriptor, but that's handled above.
+ */
+ if ((script_fd != -1) && (script_fd != JOB_PROCESS_SCRIPT_FD)) {
+ int tmp = dup2 (script_fd, JOB_PROCESS_SCRIPT_FD);
+ if (tmp < 0)
+ job_process_error_abort (fds[1], JOB_PROCESS_ERROR_DUP, 0);
+ close (script_fd);
+ script_fd = tmp;
+ }
+
/* Become the leader of a new session and process group, shedding
* any controlling tty (which we shouldn't have had anyway).
*/
@@ -664,6 +684,11 @@
err->error.number = JOB_PROCESS_ERROR;
switch (err->type) {
+ case JOB_PROCESS_ERROR_DUP:
+ err->error.message = NIH_MUST (nih_sprintf (
+ err, _("unable to move script fd: %s"),
+ strerror (err->errnum)));
+ break;
case JOB_PROCESS_ERROR_CONSOLE:
err->error.message = NIH_MUST (nih_sprintf (
err, _("unable to open console: %s"),
=== modified file 'init/job_process.h'
--- init/job_process.h 2009-07-09 11:01:53 +0000
+++ init/job_process.h 2011-05-12 19:21:16 +0000
@@ -1,5 +1,6 @@
/* upstart
*
+ * Copyright © 2011 Google Inc.
* Copyright © 2009 Canonical Ltd.
* Author: Scott James Remnant <scott@netsplit.com>.
*
@@ -32,12 +33,23 @@
/**
+ * JOB_PROCESS_SCRIPT_FD:
+ *
+ * The special fd used to pass the script to the shell process, this can be
+ * anything from 3-9 (0-2 are stdin/out/err, 10 and above aren't guaranteed
+ * by POSIX).
+ **/
+#define JOB_PROCESS_SCRIPT_FD 9
+
+
+/**
* JobProcessErrorType:
*
* These constants represent the different steps of process spawning that
* can produce an error.
**/
typedef enum job_process_error_type {
+ JOB_PROCESS_ERROR_DUP,
JOB_PROCESS_ERROR_CONSOLE,
JOB_PROCESS_ERROR_RLIMIT,
JOB_PROCESS_ERROR_PRIORITY,
@@ -80,7 +92,7 @@
int job_process_run (Job *job, ProcessType process);
pid_t job_process_spawn (JobClass *class, char * const argv[],
- char * const *env, int trace)
+ char * const *env, int trace, int script_fd)
__attribute__ ((warn_unused_result));
void job_process_kill (Job *job, ProcessType process);
=== modified file 'init/tests/test_job_process.c'
--- init/tests/test_job_process.c 2011-03-16 22:18:22 +0000
+++ init/tests/test_job_process.c 2011-05-12 19:21:16 +0000
@@ -822,7 +822,7 @@
class = job_class_new (NULL, "test");
- pid = job_process_spawn (class, args, NULL, FALSE);
+ pid = job_process_spawn (class, args, NULL, FALSE, -1);
TEST_GT (pid, 0);
waitpid (pid, NULL, 0);
@@ -860,7 +860,7 @@
class = job_class_new (NULL, "test");
class->console = CONSOLE_NONE;
- pid = job_process_spawn (class, args, NULL, FALSE);
+ pid = job_process_spawn (class, args, NULL, FALSE, -1);
TEST_GT (pid, 0);
waitpid (pid, NULL, 0);
@@ -886,7 +886,7 @@
class = job_class_new (NULL, "test");
class->chdir = "/tmp";
- pid = job_process_spawn (class, args, NULL, FALSE);
+ pid = job_process_spawn (class, args, NULL, FALSE, -1);
TEST_GT (pid, 0);
waitpid (pid, NULL, 0);
@@ -914,7 +914,7 @@
class = job_class_new (NULL, "test");
- pid = job_process_spawn (class, args, env, FALSE);
+ pid = job_process_spawn (class, args, env, FALSE, -1);
TEST_GT (pid, 0);
waitpid (pid, NULL, 0);
@@ -939,7 +939,7 @@
class = job_class_new (NULL, "test");
- pid = job_process_spawn (class, args, NULL, FALSE);
+ pid = job_process_spawn (class, args, NULL, FALSE, -1);
TEST_GT (pid, 0);
assert0 (waitid (P_PID, pid, &info, WEXITED | WSTOPPED | WCONTINUED));
@@ -959,7 +959,7 @@
class = job_class_new (NULL, "test");
- pid = job_process_spawn (class, args, NULL, TRUE);
+ pid = job_process_spawn (class, args, NULL, TRUE, -1);
TEST_GT (pid, 0);
assert0 (waitid (P_PID, pid, &info, WEXITED | WSTOPPED | WCONTINUED));
@@ -988,7 +988,7 @@
class = job_class_new (NULL, "test");
- pid = job_process_spawn (class, args, NULL, FALSE);
+ pid = job_process_spawn (class, args, NULL, FALSE, -1);
TEST_LT (pid, 0);
err = nih_error_get ();
@@ -1013,7 +1013,7 @@
args[1] = function;
args[2] = NULL;
- pid = job_process_spawn (class, args, NULL, FALSE);
+ pid = job_process_spawn (class, args, NULL, FALSE, -1);
TEST_GT (pid, 0);
/* Ensure process is still running after some period of time.