--
James Hunt
____________________________________
http://upstart.ubuntu.com/cookbook
http://upstart.ubuntu.com/cookbook/upstart_cookbook.pdf
=== modified file 'ChangeLog'
--- ChangeLog 2012-03-05 17:29:48 +0000
+++ ChangeLog 2012-03-07 12:13:28 +0000
@@ -1,3 +1,21 @@
+2012-03-07 James Hunt <[email protected]>
+
+ * init/job.c: job_new(): Initialize log array.
+ * init/job.h: Change Log element to an array to handle scenario where
+ job has multiple simultaneous processes running (LP: #940290).
+ * init/job_process.c:
+ - job_process_run(): pass ProcessType to job_process_spawn().
+ - job_process_spawn():
+ - Now accepts a ProcessType.
+ - Ensure existing matching process type log is destroyed before
+ creating a new one.
+ - job_process_terminated(): Update for log array.
+ * init/job_process.h: Updated prototype for job_process_spawn().
+ * init/tests/test_job.c: test_new(): Updated logic for log array.
+ * init/tests/test_job_process.c: test_run():
+ - Updated logic for log array.
+ - Added ProcessType to job_process_spawn() calls.
+
2012-03-05 James Hunt <[email protected]>
* init/job_process.c: job_process_spawn(): If pty setup fails,
=== modified file 'init/job.c'
--- init/job.c 2011-12-09 14:07:11 +0000
+++ init/job.c 2012-03-07 12:13:28 +0000
@@ -135,6 +135,19 @@
for (i = 0; i < PROCESS_LAST; i++)
job->pid[i] = 0;
+ /* Each job process needs its own log object to ensure sane
+ * behaviour: consider a post-start that starts and ends
+ * before the main process ends: it will be reaped (and its log
+ * flushed) before the main process has a chance to have its log
+ * drained.
+ */
+ job->log = nih_alloc (job, sizeof (Log *) * PROCESS_LAST);
+ if (! job->log)
+ goto error;
+
+ for (i = 0; i < PROCESS_LAST; i++)
+ job->log[i] = NULL;
+
job->blocker = NULL;
nih_list_init (&job->blocking);
@@ -151,8 +164,6 @@
job->trace_forks = 0;
job->trace_state = TRACE_NONE;
- job->log = NULL;
-
nih_hash_add (class->instances, &job->entry);
NIH_LIST_FOREACH (control_conns, iter) {
=== modified file 'init/job.h'
--- init/job.h 2011-12-09 14:07:11 +0000
+++ init/job.h 2012-03-07 12:13:28 +0000
@@ -115,7 +115,7 @@
* @respawn_count: number of respawns since @respawn_time,
* @trace_forks: number of forks traced,
* @trace_state: state of trace,
- * @log: pointer to log to hold job output.
+ * @log: pointer to array of log objects for handling job output.
*
* This structure holds the state of an active job instance being tracked
* by the init daemon, the configuration details of the job are available
@@ -155,7 +155,7 @@
int trace_forks;
TraceState trace_state;
- Log *log;
+ Log **log;
} Job;
=== modified file 'init/job_process.c'
--- init/job_process.c 2012-03-05 17:29:48 +0000
+++ init/job_process.c 2012-03-07 12:13:28 +0000
@@ -280,8 +280,8 @@
trace = TRUE;
/* Spawn the process, repeat until fork() works */
- while ((job->pid[process] = job_process_spawn (job, argv,
- env, trace, fds[0])) < 0) {
+ while ((job->pid[process] = job_process_spawn (job, argv, env,
+ trace, fds[0], process)) < 0) {
NihError *err;
err = nih_error_get ();
@@ -360,7 +360,8 @@
* @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,
- * @script_fd: script file descriptor.
+ * @script_fd: script file descriptor,
+ * @process: job process to spawn.
*
* This function spawns a new process using the class details in @job to set up
* the environment for it; the process is always a session and process group
@@ -395,7 +396,8 @@
char * const argv[],
char * const *env,
int trace,
- int script_fd)
+ int script_fd,
+ ProcessType process)
{
sigset_t child_set, orig_set;
pid_t pid;
@@ -415,6 +417,8 @@
nih_assert (job != NULL);
nih_assert (job->class != NULL);
+ nih_assert (job->log != NULL);
+ nih_assert (process < PROCESS_LAST);
class = job->class;
@@ -438,6 +442,15 @@
if (class->console == CONSOLE_LOG) {
NihError *err;
+ /* Ensure log destroyed for previous matching job process
+ * (occurs when job restarted but previous process has not
+ * yet been reaped).
+ */
+ if (job->log[process]) {
+ nih_free (job->log[process]);
+ job->log[process] = NULL;
+ }
+
log_path = job_process_log_path (job, 0);
if (! log_path) {
@@ -483,8 +496,8 @@
nih_io_set_cloexec (pty_master);
/* pty_master will be closed by log_destroy() */
- job->log = log_new (job, log_path, pty_master, 0);
- if (! job->log) {
+ job->log[process] = log_new (job->log, log_path, pty_master, 0);
+ if (! job->log[process]) {
close (pty_master);
close (fds[0]);
close (fds[1]);
@@ -525,8 +538,8 @@
/* Ensure the pty_master watch gets
* removed and the fd closed.
*/
- nih_free (job->log);
- job->log = NULL;
+ nih_free (job->log[process]);
+ job->log[process] = NULL;
}
close (fds[0]);
return -1;
@@ -544,8 +557,8 @@
close (fds[0]);
close (fds[1]);
if (class->console == CONSOLE_LOG) {
- nih_free (job->log);
- job->log = NULL;
+ nih_free (job->log[process]);
+ job->log[process] = NULL;
}
return -1;
}
@@ -1602,16 +1615,14 @@
job->kill_process = -1;
}
- if (job->class->console == CONSOLE_LOG) {
+ if (job->class->console == CONSOLE_LOG && job->log[process]) {
/* It is imperative that we free the log at this stage to ensure
* that jobs which respawn have their log written _now_
* (and not just when the overall Job object is freed at
* some distant future point).
*/
- if (job->log) {
- nih_free (job->log);
- job->log = NULL;
- }
+ nih_free (job->log[process]);
+ job->log[process] = NULL;
}
/* Find existing utmp entry for the process pid */
=== modified file 'init/job_process.h'
--- init/job_process.h 2011-12-12 19:21:03 +0000
+++ init/job_process.h 2012-03-07 12:13:28 +0000
@@ -125,7 +125,8 @@
int job_process_run (Job *job, ProcessType process);
pid_t job_process_spawn (Job *job, char * const argv[],
- char * const *env, int trace, int script_fd)
+ char * const *env, int trace, int script_fd,
+ ProcessType process)
__attribute__ ((warn_unused_result));
void job_process_kill (Job *job, ProcessType process);
=== modified file 'init/tests/test_job.c'
--- init/tests/test_job.c 2011-12-09 14:07:11 +0000
+++ init/tests/test_job.c 2012-03-07 12:13:28 +0000
@@ -147,7 +147,11 @@
TEST_EQ (job->trace_forks, 0);
TEST_EQ (job->trace_state, TRACE_NONE);
- TEST_EQ_P (job->log, NULL);
+ TEST_NE_P (job->log, NULL);
+ TEST_ALLOC_SIZE (job->log, sizeof (Log *) * PROCESS_LAST);
+ for (i = 0; i < PROCESS_LAST; i++) {
+ TEST_EQ_P (job->log[i], NULL);
+ }
event_operator_reset (job->stop_on);
=== modified file 'init/tests/test_job_process.c'
--- init/tests/test_job_process.c 2012-03-05 17:29:48 +0000
+++ init/tests/test_job_process.c 2012-03-07 12:13:28 +0000
@@ -416,6 +416,7 @@
int ok;
char buffer[1024];
pid_t pid;
+ int i;
TEST_FUNCTION ("job_process_run");
@@ -3727,7 +3728,12 @@
job->goal = JOB_START;
job->state = JOB_SPAWNED;
- TEST_EQ_P (job->log, NULL);
+ TEST_NE_P (job->log, NULL);
+ TEST_ALLOC_PARENT (job->log, job);
+
+ for (i = 0; i < PROCESS_LAST; i++) {
+ TEST_EQ_P (job->log[i], NULL);
+ }
ret = job_process_run (job, PROCESS_MAIN);
TEST_EQ (ret, 0);
@@ -3740,6 +3746,14 @@
TEST_NE (job->pid[PROCESS_MAIN], 0);
TEST_NE_P (job->log, NULL);
+ for (i = 0; i < PROCESS_LAST; i++) {
+ if (i == PROCESS_MAIN) {
+ TEST_NE_P (job->log[i], NULL);
+ TEST_ALLOC_PARENT (job->log[i], job->log);
+ } else {
+ TEST_EQ_P (job->log[i], NULL);
+ }
+ }
TEST_FREE_TAG (job);
TEST_FREE_TAG (job->log);
@@ -3863,7 +3877,7 @@
class->console = CONSOLE_NONE;
job = job_new (class, "");
- pid = job_process_spawn (job, args, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
waitpid (pid, NULL, 0);
@@ -3902,7 +3916,7 @@
class->console = CONSOLE_NONE;
job = job_new (class, "");
- pid = job_process_spawn (job, args, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
waitpid (pid, NULL, 0);
@@ -3932,7 +3946,7 @@
class->console = CONSOLE_LOG;
job = job_new (class, "");
- pid = job_process_spawn (job, args, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
waitpid (pid, NULL, 0);
@@ -3977,7 +3991,7 @@
class->chdir = "/tmp";
job = job_new (class, "");
- pid = job_process_spawn (job, args, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
waitpid (pid, NULL, 0);
@@ -4007,7 +4021,7 @@
class->console = CONSOLE_NONE;
job = job_new (class, "");
- pid = job_process_spawn (job, args, env, FALSE, -1);
+ pid = job_process_spawn (job, args, env, FALSE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
waitpid (pid, NULL, 0);
@@ -4035,7 +4049,7 @@
class->console = CONSOLE_NONE;
job = job_new (class, "");
- pid = job_process_spawn (job, args, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
assert0 (waitid (P_PID, pid, &info, WEXITED | WSTOPPED | WCONTINUED));
@@ -4056,7 +4070,7 @@
class = job_class_new (NULL, "test", NULL);
job = job_new (class, "");
class->console = CONSOLE_NONE;
- pid = job_process_spawn (job, args, NULL, TRUE, -1);
+ pid = job_process_spawn (job, args, NULL, TRUE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
assert0 (waitid (P_PID, pid, &info, WEXITED | WSTOPPED | WCONTINUED));
@@ -4087,7 +4101,7 @@
class->console = CONSOLE_NONE;
job = job_new (class, "");
- pid = job_process_spawn (job, args, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
TEST_LT (pid, 0);
err = nih_error_get ();
@@ -4110,8 +4124,9 @@
class->console = CONSOLE_LOG;
job = job_new (class, "");
- TEST_EQ_P (job->log, NULL);
- pid = job_process_spawn (job, args, NULL, FALSE, -1);
+ TEST_NE_P (job->log, NULL);
+ TEST_EQ_P (job->log[PROCESS_MAIN], NULL);
+ pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
TEST_LT (pid, 0);
TEST_GT (waitpid (-1, NULL, 0), 0);
@@ -4119,7 +4134,7 @@
/* The log should have been allocated in job_process_spawn,
* but then freed on error.
*/
- TEST_EQ_P (job->log, NULL);
+ TEST_EQ_P (job->log[PROCESS_MAIN], NULL);
err = nih_error_get ();
TEST_EQ (err->number, JOB_PROCESS_ERROR);
@@ -4145,7 +4160,7 @@
args[1] = function;
args[2] = NULL;
- pid = job_process_spawn (job, args, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
/* Ensure process is still running after some period of time.
@@ -4183,7 +4198,7 @@
class->console = CONSOLE_NONE;
job = job_new (class, "");
- pid = job_process_spawn (job, args, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
waitpid (pid, NULL, 0);
@@ -4226,7 +4241,7 @@
class->console = CONSOLE_LOG;
job = job_new (class, "");
- pid = job_process_spawn (job, args, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
waitpid (pid, NULL, 0);
@@ -4269,7 +4284,7 @@
class->console = CONSOLE_NONE;
job = job_new (class, "");
- pid = job_process_spawn (job, args, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
waitpid (pid, NULL, 0);
@@ -4323,7 +4338,7 @@
class->console = CONSOLE_LOG;
job = job_new (class, "");
- pid = job_process_spawn (job, args, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
waitpid (pid, NULL, 0);
@@ -4394,7 +4409,7 @@
NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, script));
}
- pid = job_process_spawn (job, args_array, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args_array, NULL, FALSE, -1, PROCESS_MAIN);
if (test_alloc_failed) {
err = nih_error_get ();
@@ -4444,7 +4459,7 @@
NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, TEST_SHELL_ARG));
NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, script));
- pid = job_process_spawn (job, args_array, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args_array, NULL, FALSE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
TEST_EQ (waitpid (pid, &status, 0), pid);
@@ -4498,7 +4513,7 @@
NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, TEST_SHELL_ARG));
NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, script));
- pid = job_process_spawn (job, args_array, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args_array, NULL, FALSE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
TEST_EQ (waitpid (pid, &status, 0), pid);
@@ -4548,7 +4563,7 @@
NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, "-en"));
NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, "\\000"));
- pid = job_process_spawn (job, args_array, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args_array, NULL, FALSE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
TEST_EQ (waitpid (pid, &status, 0), pid);
@@ -4600,7 +4615,7 @@
args[3] = filebuf;
args[4] = NULL;
- pid = job_process_spawn (job, args, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
TEST_EQ (waitpid (pid, &status, 0), pid);
@@ -4653,7 +4668,7 @@
args[3] = filebuf;
args[4] = NULL;
- pid = job_process_spawn (job, args, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
TEST_GT (pid, 0);
TEST_FORCE_WATCH_UPDATE ();
@@ -4733,7 +4748,7 @@
}
}
- pid = job_process_spawn (job, args, NULL, FALSE, -1);
+ pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
TEST_LT (pid, 0);
/* Ensure logging disabled in failure scenarios */
--
upstart-devel mailing list
[email protected]
Modify settings or unsubscribe at:
https://lists.ubuntu.com/mailman/listinfo/upstart-devel