--
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

Reply via email to