Merge lp:~xnox/upstart/async-remove-duplicate-event into lp:upstart/async

Proposed by Dimitri John Ledkov
Status: Superseded
Proposed branch: lp:~xnox/upstart/async-remove-duplicate-event
Merge into: lp:upstart/async
Diff against target: 2287 lines (+235/-1090)
8 files modified
init/job.c (+4/-17)
init/job.h (+0/-2)
init/job_process.c (+0/-837)
init/job_process.h (+1/-5)
init/tests/test_event.c (+4/-2)
init/tests/test_job.c (+4/-19)
init/tests/test_job_process.c (+187/-208)
test/test_util_common.h (+35/-0)
To merge this branch: bzr merge lp:~xnox/upstart/async-remove-duplicate-event
Reviewer Review Type Date Requested Status
James Hunt Pending
Review via email: mp+220538@code.launchpad.net

This proposal has been superseded by a proposal from 2014-05-21.

To post a comment you must log in.
Revision history for this message
Dimitri John Ledkov (xnox) wrote :

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'init/job.c'
2--- init/job.c 2014-05-20 13:23:17 +0000
3+++ init/job.c 2014-05-21 22:39:37 +0000
4@@ -978,23 +978,8 @@
5
6
7 /**
8- * job_emit_event:
9- * @job: job generating the event,
10- *
11- * Compat function, for migration to job_emit_event_with_state.
12- *
13- * Returns: new Event in the queue.
14- **/
15-Event *
16-job_emit_event (Job *job)
17-{
18- return job_emit_event_with_state (job, job->state);
19-}
20-
21-/**
22 * job_emit_event_with_state:
23 * @job: job generating the event,
24- * @state: state job is moving to.
25 *
26 * Called from a state change because it believes an event should be
27 * emitted. Constructs the event with the right arguments and environment
28@@ -1012,7 +997,7 @@
29 * Returns: new Event in the queue.
30 **/
31 Event *
32-job_emit_event_with_state (Job *job, JobState state)
33+job_emit_event (Job *job)
34 {
35 Event *event;
36 const char *name;
37@@ -1023,7 +1008,7 @@
38
39 nih_assert (job != NULL);
40
41- switch (state) {
42+ switch (job->state) {
43 case JOB_STARTING:
44 name = JOB_STARTING_EVENT;
45 block = TRUE;
46@@ -2595,6 +2580,8 @@
47 nih_assert (process > PROCESS_INVALID);
48 nih_assert (process < PROCESS_LAST);
49
50+ job->pid[process] = 0;
51+
52 switch (process) {
53 case PROCESS_SECURITY:
54 job_failed (job, PROCESS_SECURITY, -1);
55
56=== modified file 'init/job.h'
57--- init/job.h 2014-05-16 12:12:20 +0000
58+++ init/job.h 2014-05-21 22:39:37 +0000
59@@ -238,8 +238,6 @@
60 void job_finished (Job *job, int failed);
61
62 Event *job_emit_event (Job *job);
63-Event *job_emit_event_with_state (Job *job, JobState state);
64-
65
66 const char *job_name (Job *job);
67
68
69=== modified file 'init/job_process.c'
70--- init/job_process.c 2014-05-21 16:52:42 +0000
71+++ init/job_process.c 2014-05-21 22:39:37 +0000
72@@ -111,8 +111,6 @@
73 static void job_process_error_abort (int fd, JobProcessErrorType type,
74 int arg)
75 __attribute__ ((noreturn));
76-static int job_process_error_read (int fd)
77- __attribute__ ((warn_unused_result));
78 static void job_process_remap_fd (int *fd, int reserved_fd, int error_fd);
79
80 /**
81@@ -149,802 +147,6 @@
82 extern int session_end;
83 extern time_t quiesce_phase_time;
84
85-/**
86- * job_process_run:
87- * @job: job context for process to be run in,
88- * @process: job process to run.
89- *
90- * This function looks up @process in the job's process table and uses
91- * the information there to spawn a new process for the @job, storing the
92- * pid in that table entry.
93- *
94- * The process is normally executed using the system shell, unless the
95- * script member of @process is FALSE and there are no typical shell
96- * characters within the command member, in which case it is executed
97- * directly using exec after splitting on whitespace.
98- *
99- * When executed with the shell, if the command (which may be an entire
100- * script) is reasonably small (less than 1KB) it is passed to the
101- * shell using the POSIX-specified -c option. Otherwise the shell is told
102- * to read commands from one of the special /proc/self/fd/NN devices and NihIo
103- * used to feed the script into that device. A pointer to the NihIo object
104- * is not kept or stored because it will automatically clean itself up should
105- * the script go away as the other end of the pipe will be closed.
106- *
107- * In either case the shell is run with the -e option so that commands will
108- * fail if their exit status is not checked.
109- *
110- * This function will block until the job_process_spawn() call succeeds or
111- * a non-temporary error occurs (such as file not found). It is up to the
112- * called to decide whether non-temporary errors are a reason to change the
113- * job state or not.
114- *
115- * Returns: zero on success, negative value on non-temporary error.
116- **/
117-int
118-job_process_run (Job *job,
119- ProcessType process)
120-{
121- Process *proc;
122- nih_local char **argv = NULL;
123- nih_local char **env = NULL;
124- nih_local char *script = NULL;
125- char **e;
126- size_t argc, envc;
127- int fds[2] = { -1, -1 };
128- int error = FALSE, trace = FALSE, shell = FALSE;
129-
130- nih_assert (job != NULL);
131-
132- proc = job->class->process[process];
133- nih_assert (proc != NULL);
134- nih_assert (proc->command != NULL);
135-
136- /* We run the process using a shell if it says it wants to be run
137- * as such, or if it contains any shell-like characters; since that's
138- * the best way to deal with things like variables.
139- */
140- if ((proc->script) || strpbrk (proc->command, SHELL_CHARS)) {
141- char *nl, *p;
142-
143- argc = 0;
144- argv = NIH_MUST (nih_str_array_new (NULL));
145-
146- NIH_MUST (nih_str_array_add (&argv, NULL, &argc, SHELL));
147- NIH_MUST (nih_str_array_add (&argv, NULL, &argc, "-e"));
148-
149- /* If the process wasn't originally marked to be run through
150- * a shell, prepend exec to the script so that the shell
151- * gets out of the way after parsing.
152- */
153- if (proc->script) {
154- script = NIH_MUST (nih_strdup (NULL, proc->command));
155- } else {
156- script = NIH_MUST (nih_sprintf (NULL, "exec %s",
157- proc->command));
158- }
159-
160- /* Don't pipe single-line scripts into the shell using
161- * /proc/self/fd/NNN, instead just pass them over the
162- * command-line (taking care to strip off the trailing
163- * newlines).
164- */
165- p = nl = strchr (script, '\n');
166- while (p && (*p == '\n'))
167- p++;
168-
169- if ((! nl) || (! *p)) {
170- /* Strip off the newline(s) */
171- if (nl)
172- *nl = '\0';
173-
174- NIH_MUST (nih_str_array_add (&argv, NULL,
175- &argc, "-c"));
176- NIH_MUST (nih_str_array_addp (&argv, NULL,
177- &argc, script));
178-
179- /* Next argument is argv[0]; just pass the shell */
180- NIH_MUST (nih_str_array_add (&argv, NULL,
181- &argc, SHELL));
182- } else {
183- nih_local char *cmd = NULL;
184-
185- /* Close the writing end when the child is exec'd */
186- NIH_ZERO (pipe (fds));
187- nih_io_set_cloexec (fds[1]);
188-
189- shell = TRUE;
190-
191- cmd = NIH_MUST (nih_sprintf (argv, "%s/%d",
192- "/proc/self/fd",
193- JOB_PROCESS_SCRIPT_FD));
194- NIH_MUST (nih_str_array_addp (&argv, NULL,
195- &argc, cmd));
196- }
197- } else {
198- /* Split the command on whitespace to produce a list of
199- * arguments that we can exec directly.
200- */
201- argv = NIH_MUST (nih_str_split (NULL, proc->command,
202- " \t\r\n", TRUE));
203- }
204-
205- /* We provide the standard job environment to all of its processes,
206- * except for pre-stop which also has the stop event environment,
207- * adding special variables that indicate which job it was -- mostly
208- * so that initctl can have clever behaviour when called within them.
209- */
210- envc = 0;
211- env = NIH_MUST (nih_str_array_new (NULL));
212-
213- if (job->env)
214- NIH_MUST (environ_append (&env, NULL, &envc, TRUE, job->env));
215-
216- if (job->stop_env
217- && ((process == PROCESS_PRE_STOP)
218- || (process == PROCESS_POST_STOP)))
219- for (e = job->stop_env; *e; e++)
220- NIH_MUST (environ_set (&env, NULL, &envc, TRUE, *e));
221-
222- NIH_MUST (environ_set (&env, NULL, &envc, TRUE,
223- "UPSTART_JOB=%s", job->class->name));
224- NIH_MUST (environ_set (&env, NULL, &envc, TRUE,
225- "UPSTART_INSTANCE=%s", job->name));
226- if (user_mode)
227- NIH_MUST (environ_set (&env, NULL, &envc, TRUE,
228- "UPSTART_SESSION=%s", control_server_address));
229-
230- /* If we're about to spawn the main job and we expect it to become
231- * a daemon or fork before we can move out of spawned, we need to
232- * set a trace on it.
233- */
234- if ((process == PROCESS_MAIN)
235- && ((job->class->expect == EXPECT_DAEMON)
236- || (job->class->expect == EXPECT_FORK)))
237- trace = TRUE;
238-
239- /* Spawn the process, repeat until fork() works */
240- while ((job->pid[process] = job_process_spawn (job, argv, env,
241- trace, fds[0], process)) < 0) {
242- NihError *err;
243-
244- err = nih_error_get ();
245- if (err->number == JOB_PROCESS_ERROR) {
246- /* Non-temporary error condition, we're not going
247- * to be able to spawn this process. Clean up after
248- * ourselves before returning.
249- */
250- if (shell) {
251- close (fds[0]);
252- close (fds[1]);
253- }
254-
255- job->pid[process] = 0;
256-
257- /* Return non-temporary error condition */
258- nih_warn (_("Failed to spawn %s %s process: %s"),
259- job_name (job), process_name (process),
260- err->message);
261- nih_free (err);
262- return -1;
263- } else if (! error)
264- nih_warn ("%s: %s", _("Temporary process spawn error"),
265- err->message);
266- nih_free (err);
267-
268- error = TRUE;
269- }
270-
271- nih_info (_("%s %s process (%d)"),
272- job_name (job), process_name (process), job->pid[process]);
273-
274- job->trace_forks = 0;
275- job->trace_state = trace ? TRACE_NEW : TRACE_NONE;
276-
277- /* Feed the script to the child process */
278- if (shell) {
279- NihIo *io;
280-
281- /* Clean up and close the reading end (we don't need it) */
282- close (fds[0]);
283-
284- /* Put the entire script into an NihIo send buffer and
285- * then mark it for closure so that the shell gets EOF
286- * and the structure gets cleaned up automatically.
287- */
288- while (! (io = nih_io_reopen (job, fds[1], NIH_IO_STREAM,
289- NULL, NULL, NULL, NULL))) {
290- NihError *err;
291-
292- err = nih_error_get ();
293- if (err->number != ENOMEM)
294- nih_assert_not_reached ();
295- nih_free (err);
296- }
297-
298- /* We're feeding using a pipe, which has a file descriptor
299- * on the child end even though it open()s it again using
300- * a path. Instruct the shell to close this extra fd and
301- * not to leak it.
302- */
303- NIH_ZERO (nih_io_printf (io, "exec %d<&-\n",
304- JOB_PROCESS_SCRIPT_FD));
305-
306- NIH_ZERO (nih_io_write (io, script, strlen (script)));
307- nih_io_shutdown (io);
308- }
309-
310- return 0;
311-}
312-
313-
314-/**
315- * job_process_spawn:
316- * @job: job of process to be spawned,
317- * @argv: NULL-terminated list of arguments for the process,
318- * @env: NULL-terminated list of environment variables for the process,
319- * @trace: whether to trace this process,
320- * @script_fd: script file descriptor,
321- * @process: job process to spawn.
322- *
323- * This function spawns a new process using the class details in @job to set up
324- * the environment for it; the process is always a session and process group
325- * leader as we never want anything in our own group.
326- *
327- * The process to be executed is given in the @argv array which is passed
328- * directly to execvp(), so should be in the same NULL-terminated form with
329- * the first argument containing the path or filename of the binary. The
330- * PATH environment in the @job's associated class will be searched.
331- *
332- * If @trace is TRUE, the process will be traced with ptrace and this will
333- * cause the process to be stopped when the exec() call is made. You must
334- * wait for this and then may use it to set options before continuing the
335- * process.
336- *
337- * If @script_fd is not -1, this file descriptor is dup()d to the special fd 9
338- * (moving any other out of the way if necessary).
339- *
340- * This function only spawns the process, it is up to the caller to ensure
341- * that the information is saved into the job and that the process is watched,
342- * etc.
343- *
344- * Spawning a process may fail for temporary reasons, usually due to a failure
345- * of the fork() syscall or communication with the child; or more permanent
346- * reasons such as a failure to setup the child environment. These latter
347- * are always represented by a JOB_PROCESS_ERROR error.
348- *
349- * Returns: process id of new process on success, -1 on raised error
350- **/
351-pid_t
352-job_process_spawn (Job *job,
353- char * const argv[],
354- char * const *env,
355- int trace,
356- int script_fd,
357- ProcessType process)
358-{
359- sigset_t child_set, orig_set;
360- pid_t pid;
361- int i, fds[2];
362- int pty_master = -1;
363- int pty_slave = -1;
364- char pts_name[PATH_MAX];
365- char filename[PATH_MAX];
366- FILE *fd;
367- nih_local char *log_path = NULL;
368- JobClass *class;
369- uid_t job_setuid = -1;
370- gid_t job_setgid = -1;
371- struct passwd *pwd = NULL;
372- struct group *grp = NULL;
373-
374-
375- nih_assert (job != NULL);
376- nih_assert (job->class != NULL);
377- nih_assert (job->log != NULL);
378- nih_assert (process < PROCESS_LAST);
379-
380- class = job->class;
381-
382- nih_assert (class != NULL);
383-
384- /* Create a pipe to communicate with the child process until it
385- * execs so we know whether that was successful or an error occurred.
386- */
387- if (pipe (fds) < 0)
388- nih_return_system_error (-1);
389-
390- if (class->console == CONSOLE_LOG && disable_job_logging)
391- class->console = CONSOLE_NONE;
392-
393- if (class->console == CONSOLE_LOG) {
394- NihError *err;
395-
396- /* Ensure log destroyed for previous matching job process
397- * (occurs when job restarted but previous process has not
398- * yet been reaped).
399- */
400- if (job->log[process]) {
401- nih_free (job->log[process]);
402- job->log[process] = NULL;
403- }
404-
405- log_path = job_process_log_path (job, 0);
406-
407- if (! log_path) {
408- /* Consume and re-raise */
409- err = nih_error_get ();
410- nih_assert (err->number == ENOMEM);
411- nih_free (err);
412- close (fds[0]);
413- close (fds[1]);
414- nih_return_no_memory_error(-1);
415- }
416-
417- pty_master = posix_openpt (O_RDWR | O_NOCTTY);
418-
419- if (pty_master < 0) {
420- nih_error (_("Failed to create pty - disabling logging for job"));
421-
422- /* Ensure that the job can still be started by
423- * disabling logging.
424- */
425- class->console = CONSOLE_NONE;
426-
427- close (fds[0]);
428- close (fds[1]);
429- nih_return_system_error (-1);
430- }
431-
432- /* Stop any process created _before_ the log object below is
433- * freed from inheriting this fd.
434- */
435- nih_io_set_cloexec (pty_master);
436-
437- /* pty_master will be closed by log_destroy() */
438- job->log[process] = log_new (job->log, log_path, pty_master, 0);
439- if (! job->log[process]) {
440- close (pty_master);
441- close (fds[0]);
442- close (fds[1]);
443- nih_return_system_error (-1);
444- }
445- }
446-
447- /* Block all signals while we fork to avoid the child process running
448- * our own signal handlers before we've reset them all back to the
449- * default.
450- */
451- sigfillset (&child_set);
452- sigprocmask (SIG_BLOCK, &child_set, &orig_set);
453-
454- /* Ensure that any lingering data in stdio buffers is flushed
455- * to avoid the child getting a copy of it.
456- * If not done, CONSOLE_LOG jobs may end up with unexpected data
457- * in their logs if we run with for example '--debug'.
458- */
459- fflush (NULL);
460-
461- /* Fork the child process, handling success and failure by resetting
462- * the signal mask and returning the new process id or a raised error.
463- */
464- pid = fork ();
465- if (pid > 0) {
466- if (class->debug) {
467- nih_info (_("Pausing %s (%d) [pre-exec] for debug"),
468- class->name, pid);
469- }
470-
471- sigprocmask (SIG_SETMASK, &orig_set, NULL);
472- close (fds[1]);
473-
474- /* Read error from the pipe, return if one is raised */
475- if (job_process_error_read (fds[0]) < 0) {
476- if (class->console == CONSOLE_LOG) {
477- /* Ensure the pty_master watch gets
478- * removed and the fd closed.
479- */
480- nih_free (job->log[process]);
481- job->log[process] = NULL;
482- }
483- close (fds[0]);
484- return -1;
485- }
486-
487- /* Note that pts_master is closed automatically in the parent when the
488- * log object is destroyed.
489- */
490- close (fds[0]);
491- return pid;
492- } else if (pid < 0) {
493- nih_error_raise_system ();
494-
495- sigprocmask (SIG_SETMASK, &orig_set, NULL);
496- close (fds[0]);
497- close (fds[1]);
498- if (class->console == CONSOLE_LOG) {
499- nih_free (job->log[process]);
500- job->log[process] = NULL;
501- }
502- return -1;
503- }
504-
505- /* We're now in the child process.
506- *
507- * The rest of this function sets the child up and ends by executing
508- * the new binary. Failures are handled by terminating the child
509- * and writing an error back to the parent.
510- */
511-
512- /* Close the reading end of the pipe with our parent and mark the
513- * writing end to be closed-on-exec so the parent knows we got that
514- * far because read() returned zero.
515- */
516- close (fds[0]);
517-
518- job_process_remap_fd (&fds[1], JOB_PROCESS_SCRIPT_FD, fds[1]);
519- nih_io_set_cloexec (fds[1]);
520-
521- if (class->console == CONSOLE_LOG) {
522- struct sigaction act;
523- struct sigaction ignore;
524-
525- job_process_remap_fd (&pty_master, JOB_PROCESS_SCRIPT_FD, fds[1]);
526-
527- /* Child is the slave, so won't need this */
528- nih_io_set_cloexec (pty_master);
529-
530- /* Temporarily disable child handler as grantpt(3) disallows one
531- * being in effect when called.
532- */
533- ignore.sa_handler = SIG_DFL;
534- ignore.sa_flags = 0;
535- sigemptyset (&ignore.sa_mask);
536-
537- if (sigaction (SIGCHLD, &ignore, &act) < 0) {
538- nih_error_raise_system ();
539- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SIGNAL, 0);
540- }
541-
542- if (grantpt (pty_master) < 0) {
543- nih_error_raise_system ();
544- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GRANTPT, 0);
545- }
546-
547- /* Restore child handler */
548- if (sigaction (SIGCHLD, &act, NULL) < 0) {
549- nih_error_raise_system ();
550- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SIGNAL, 0);
551- }
552-
553- if (unlockpt (pty_master) < 0) {
554- nih_error_raise_system ();
555- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_UNLOCKPT, 0);
556- }
557-
558- if (ptsname_r (pty_master, pts_name, sizeof(pts_name)) < 0) {
559- nih_error_raise_system ();
560- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_PTSNAME, 0);
561- }
562-
563- pty_slave = open (pts_name, O_RDWR | O_NOCTTY);
564-
565- if (pty_slave < 0) {
566- nih_error_raise_system ();
567- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_OPENPT_SLAVE, 0);
568- }
569-
570- job_process_remap_fd (&pty_slave, JOB_PROCESS_SCRIPT_FD, fds[1]);
571- }
572-
573- /* Move the script fd to special fd 9; the only gotcha is if that
574- * would be our error descriptor, but that's handled above.
575- */
576- if ((script_fd != -1) && (script_fd != JOB_PROCESS_SCRIPT_FD)) {
577- int tmp = dup2 (script_fd, JOB_PROCESS_SCRIPT_FD);
578- if (tmp < 0) {
579- nih_error_raise_system ();
580- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_DUP, 0);
581- }
582- close (script_fd);
583- script_fd = tmp;
584- }
585-
586- /* Become the leader of a new session and process group, shedding
587- * any controlling tty (which we shouldn't have had anyway).
588- */
589- setsid ();
590-
591- /* Set the process environment from the function parameters. */
592- environ = (char **)env;
593-
594- /* Set the standard file descriptors to an output of our chosing;
595- * any other open descriptor must be intended for the child, or have
596- * the FD_CLOEXEC flag so it's automatically closed when we exec()
597- * later.
598- */
599- if (system_setup_console (class->console, FALSE) < 0) {
600- if (class->console == CONSOLE_OUTPUT) {
601- NihError *err;
602-
603- err = nih_error_get ();
604- nih_warn (_("Failed to open system console: %s"),
605- err->message);
606- nih_free (err);
607-
608- if (system_setup_console (CONSOLE_NONE, FALSE) < 0)
609- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CONSOLE, 0);
610- } else
611- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CONSOLE, 0);
612- }
613-
614- if (class->console == CONSOLE_LOG) {
615- /* Redirect stdout and stderr to the logger fd */
616- if (dup2 (pty_slave, STDOUT_FILENO) < 0) {
617- nih_error_raise_system ();
618- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_DUP, 0);
619- }
620-
621- if (dup2 (pty_slave, STDERR_FILENO) < 0) {
622- nih_error_raise_system ();
623- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_DUP, 0);
624- }
625-
626- close (pty_slave);
627- }
628-
629- /* Switch to the specified AppArmor profile, but only for the main
630- process, so we don't confine the pre- and post- processes.
631- */
632- if ((class->apparmor_switch) && (process == PROCESS_MAIN)) {
633- nih_local char *profile = NULL;
634-
635- /* Use the environment to expand the AppArmor profile name
636- */
637- profile = NIH_SHOULD (environ_expand (NULL,
638- class->apparmor_switch,
639- environ));
640-
641- if (! profile) {
642- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SECURITY, 0);
643- }
644-
645- if (apparmor_switch (profile) < 0) {
646- nih_error_raise_system ();
647- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SECURITY, 0);
648- }
649- }
650-
651- if (process != PROCESS_SECURITY) {
652- /* Set resource limits for the process, skipping over any that
653- * aren't set in the job class such that they inherit from
654- * ourselves (and we inherit from kernel defaults).
655- */
656- for (i = 0; i < RLIMIT_NLIMITS; i++) {
657- if (! class->limits[i])
658- continue;
659-
660- if (setrlimit (i, class->limits[i]) < 0) {
661- nih_error_raise_system ();
662- job_process_error_abort (fds[1],
663- JOB_PROCESS_ERROR_RLIMIT, i);
664- }
665- }
666-
667- /* Set the file mode creation mask; this is one of the few operations
668- * that can never fail.
669- */
670- umask (class->umask);
671-
672- /* Adjust the process priority ("nice level").
673- */
674- if (class->nice != JOB_NICE_INVALID &&
675- setpriority (PRIO_PROCESS, 0, class->nice) < 0) {
676- nih_error_raise_system ();
677- job_process_error_abort (fds[1],
678- JOB_PROCESS_ERROR_PRIORITY, 0);
679- }
680-
681- /* Adjust the process OOM killer priority.
682- */
683- if (class->oom_score_adj != JOB_DEFAULT_OOM_SCORE_ADJ) {
684- int oom_value;
685- snprintf (filename, sizeof (filename),
686- "/proc/%d/oom_score_adj", getpid ());
687- oom_value = class->oom_score_adj;
688- fd = fopen (filename, "w");
689- if ((! fd) && (errno == ENOENT)) {
690- snprintf (filename, sizeof (filename),
691- "/proc/%d/oom_adj", getpid ());
692- oom_value = (class->oom_score_adj
693- * ((class->oom_score_adj < 0) ? 17 : 15)) / 1000;
694- fd = fopen (filename, "w");
695- }
696- if (! fd) {
697- nih_error_raise_system ();
698- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_OOM_ADJ, 0);
699- } else {
700- fprintf (fd, "%d\n", oom_value);
701-
702- if (fclose (fd)) {
703- nih_error_raise_system ();
704- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_OOM_ADJ, 0);
705- }
706- }
707- }
708-
709- /* Handle changing a chroot session job prior to dealing with
710- * the 'chroot' stanza.
711- */
712- if (class->session && class->session->chroot) {
713- if (chroot (class->session->chroot) < 0) {
714- nih_error_raise_system ();
715- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CHROOT, 0);
716- }
717- }
718-
719- /* Change the root directory, confining path resolution within it;
720- * we do this before the working directory call so that is always
721- * relative to the new root.
722- */
723- if (class->chroot) {
724- if (chroot (class->chroot) < 0) {
725- nih_error_raise_system ();
726- job_process_error_abort (fds[1],
727- JOB_PROCESS_ERROR_CHROOT, 0);
728- }
729- }
730-
731- /* Change the working directory of the process, either to the one
732- * configured in the job, or to the root directory of the filesystem
733- * (or at least relative to the chroot).
734- */
735- if (class->chdir || user_mode == FALSE) {
736- if (chdir (class->chdir ? class->chdir : "/") < 0) {
737- nih_error_raise_system ();
738- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CHDIR, 0);
739- }
740- }
741-
742- /* Change the user and group of the process to the one
743- * configured in the job. We must wait until now to lookup the
744- * UID and GID from the names to accommodate both chroot
745- * session jobs and jobs with a chroot stanza.
746- */
747- if (class->setuid) {
748- /* Without resetting errno, it's impossible to
749- * distinguish between a non-existent user and and
750- * error during lookup */
751- errno = 0;
752- pwd = getpwnam (class->setuid);
753- if (! pwd) {
754- if (errno != 0) {
755- nih_error_raise_system ();
756- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GETPWNAM, 0);
757- } else {
758- nih_error_raise (JOB_PROCESS_INVALID_SETUID,
759- JOB_PROCESS_INVALID_SETUID_STR);
760- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_BAD_SETUID, 0);
761- }
762- }
763-
764- job_setuid = pwd->pw_uid;
765- /* This will be overridden if setgid is also set: */
766- job_setgid = pwd->pw_gid;
767- }
768-
769- if (class->setgid) {
770- errno = 0;
771- grp = getgrnam (class->setgid);
772- if (! grp) {
773- if (errno != 0) {
774- nih_error_raise_system ();
775- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GETGRNAM, 0);
776- } else {
777- nih_error_raise (JOB_PROCESS_INVALID_SETGID,
778- JOB_PROCESS_INVALID_SETGID_STR);
779- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_BAD_SETGID, 0);
780- }
781- }
782-
783- job_setgid = grp->gr_gid;
784- }
785-
786- if (script_fd != -1 &&
787- (job_setuid != (uid_t) -1 || job_setgid != (gid_t) -1) &&
788- fchown (script_fd, job_setuid, job_setgid) < 0) {
789- nih_error_raise_system ();
790- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CHOWN, 0);
791- }
792-
793- /* Make sure we always have the needed pwd and grp structs.
794- * Then pass those to initgroups() to setup the user's group list.
795- * Only do that if we're root as initgroups() won't work when non-root. */
796- if (geteuid () == 0) {
797- if (! pwd) {
798- pwd = getpwuid (geteuid ());
799- if (! pwd) {
800- nih_error_raise_system ();
801- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GETPWUID, 0);
802- }
803- }
804-
805- if (! grp) {
806- grp = getgrgid (getegid ());
807- if (! grp) {
808- nih_error_raise_system ();
809- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_GETGRGID, 0);
810- }
811- }
812-
813- if (pwd && grp) {
814- if (initgroups (pwd->pw_name, grp->gr_gid) < 0) {
815- nih_error_raise_system ();
816- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_INITGROUPS, 0);
817- }
818- }
819- }
820-
821- /* Start dropping privileges */
822- if (job_setgid != (gid_t) -1 && setgid (job_setgid) < 0) {
823- nih_error_raise_system ();
824- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SETGID, 0);
825- }
826-
827- if (job_setuid != (uid_t)-1 && setuid (job_setuid) < 0) {
828- nih_error_raise_system ();
829- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SETUID, 0);
830- }
831- }
832-
833- /* Reset all the signal handlers back to their default handling so
834- * the child isn't unexpectedly ignoring any, and so we won't
835- * surprisingly handle them before we've exec()d the new process.
836- */
837- nih_signal_reset ();
838- sigprocmask (SIG_SETMASK, &orig_set, NULL);
839-
840- /* Notes:
841- *
842- * - we can't use pause() here since there would then be no way to
843- * resume the process without killing it.
844- *
845- * - we have to close the pipe back to the parent since if we don't,
846- * the parent hangs until the STOP is cleared. Although this may be
847- * acceptable for normal operation, this causes the test suite to
848- * fail. Note that closing the pipe means from this point onwards,
849- * the parent cannot know the true outcome of the spawn: that
850- * responsibility lies with the debugger.
851- *
852- * - note that running with the debug stanza enabled will
853- * unavoidably stop stateful re-exec from working correctly
854- * since the stopped debug child process will hold copies of
855- * the parents file descriptors open until it continues to
856- * call exec below.
857- */
858- if (class->debug) {
859- close (fds[1]);
860- raise (SIGSTOP);
861- }
862-
863- /* Set up a process trace if we need to trace forks */
864- if (trace) {
865- if (ptrace (PTRACE_TRACEME, 0, NULL, 0) < 0) {
866- nih_error_raise_system();
867- job_process_error_abort (fds[1],
868- JOB_PROCESS_ERROR_PTRACE, 0);
869- }
870- }
871-
872- /* Execute the process, if we escape from here it failed */
873- if (execvp (argv[0], argv) < 0) {
874- nih_error_raise_system ();
875- job_process_error_abort (fds[1], JOB_PROCESS_ERROR_EXEC, 0);
876- }
877-
878- nih_assert_not_reached ();
879-}
880-
881
882 /**
883 * job_process_start:
884@@ -1761,45 +963,6 @@
885 exit (255);
886 }
887
888-/**
889- * job_process_error_read:
890- * @fd: reading end of pipe.
891- *
892- * Read from the reading end of the pipe specified by @fd, if we receive
893- * data then the child raised a process error which we reconstruct and raise
894- * again; otherwise no problem was found and no action is taken.
895- *
896- * The reconstructed error will be of JOB_PROCESS_ERROR type, the human-
897- * readable message is generated according to the type of process error
898- * and argument passed along with it.
899- *
900- * Returns: zero if no error was found, or negative value on raised error.
901- **/
902-static int
903-job_process_error_read (int fd)
904-{
905- JobProcessWireError wire_err;
906- ssize_t len;
907-
908- /* Read the error from the pipe; a zero read indicates that the
909- * exec succeeded so we return success, otherwise if we don't receive
910- * a JobProcessWireError structure, we return a temporary error so we
911- * try again.
912- */
913- len = read (fd, &wire_err, sizeof (wire_err));
914- if (len == 0) {
915- return 0;
916- } else if (len < 0) {
917- nih_return_system_error (-1);
918- } else if (len != sizeof (wire_err)) {
919- errno = EILSEQ;
920- nih_return_system_error (-1);
921- }
922-
923- job_process_error_handler ((char *)(&wire_err), len);
924- return -1;
925-}
926-
927
928 /**
929 * job_process_error_handler:
930
931=== modified file 'init/job_process.h'
932--- init/job_process.h 2014-05-15 09:43:13 +0000
933+++ init/job_process.h 2014-05-21 22:39:37 +0000
934@@ -138,11 +138,7 @@
935
936 NIH_BEGIN_EXTERN
937
938-int job_process_run (Job *job, ProcessType process);
939-void
940-job_process_start (Job *job,
941- ProcessType process);
942-
943+void job_process_start (Job *job, ProcessType process);
944 void job_process_run_bottom (JobProcessData *handler_data);
945
946 void job_process_child_reader (JobProcessData *handler_data, NihIo *io,
947
948=== modified file 'init/tests/test_event.c'
949--- init/tests/test_event.c 2014-05-19 16:52:28 +0000
950+++ init/tests/test_event.c 2014-05-21 22:39:37 +0000
951@@ -1730,8 +1730,10 @@
952 nih_hash_add (job_classes, &class->entry);
953 }
954
955- event_poll ();
956-
957+ //FIXME must run without TEST_ALLOC_SAFE
958+ TEST_ALLOC_SAFE {
959+ event_poll ();
960+ }
961 TEST_FREE (event);
962
963 TEST_HASH_NOT_EMPTY (class->instances);
964
965=== modified file 'init/tests/test_job.c'
966--- init/tests/test_job.c 2014-05-20 21:14:25 +0000
967+++ init/tests/test_job.c 2014-05-21 22:39:37 +0000
968@@ -60,6 +60,7 @@
969 #include "conf.h"
970 #include "control.h"
971 #include "state.h"
972+#include "test_util_common.h"
973
974 void
975 job_quit_with_state (void *data, NihMainLoopFunc *loop)
976@@ -69,12 +70,6 @@
977 nih_main_loop_exit (job->state);
978 }
979
980-void
981-timeout_quit_zero (void *data, NihTimerCb *timer)
982-{
983- nih_main_loop_exit (0);
984-}
985-
986 char *argv0;
987
988 static int state_fd = -1;
989@@ -1234,8 +1229,7 @@
990 TEST_EQ (job->goal, JOB_STOP);
991 TEST_EQ (job->state, JOB_STOPPING);
992 TEST_FALSE (job->process_data[PROCESS_PRE_START]->valid);
993- // FIXME shouldn't it be zero at this point?
994- TEST_NE (job->pid[PROCESS_PRE_START], 0);
995+ TEST_EQ (job->pid[PROCESS_PRE_START], 0);
996
997 TEST_EQ (cause->blockers, 0);
998 TEST_EQ (cause->failed, TRUE);
999@@ -1616,8 +1610,7 @@
1000 TEST_EQ (job->goal, JOB_STOP);
1001 TEST_EQ (job->state, JOB_STOPPING);
1002 TEST_FALSE (job->process_data[PROCESS_MAIN]->valid);
1003- // FIXME shouldn't it be zero at this point?
1004- TEST_NE (job->pid[PROCESS_MAIN], 0);
1005+ TEST_EQ (job->pid[PROCESS_MAIN], 0);
1006
1007 TEST_EQ (cause->blockers, 0);
1008 TEST_EQ (cause->failed, TRUE);
1009@@ -3246,10 +3239,7 @@
1010 TEST_FEATURE ("killed to post-stop for failed process");
1011 tmp = class->process[PROCESS_POST_STOP];
1012 class->process[PROCESS_POST_STOP] = fail;
1013- NihTimer * timer;
1014
1015- /* FIXME this is very slow, as we wait 1s per TEST_ALLOC_FAIL itteration... */
1016- nih_message (" Running. Respect the timer.");
1017 TEST_ALLOC_FAIL {
1018 TEST_ALLOC_SAFE {
1019 job = job_new (class, "");
1020@@ -3257,7 +3247,6 @@
1021 blocked = blocked_new (job, BLOCKED_EVENT, cause);
1022 event_block (cause);
1023 nih_list_add (&job->blocking, &blocked->entry);
1024- timer = nih_timer_add_timeout (NULL, 1, (NihTimerCb)timeout_quit_zero, NULL);
1025 }
1026
1027 job->goal = JOB_START;
1028@@ -3274,16 +3263,12 @@
1029
1030 TEST_FREE_TAG (job);
1031
1032- TEST_FREE_TAG (timer);
1033-
1034 TEST_DIVERT_STDERR (output) {
1035 job_change_state (job, JOB_POST_STOPPING);
1036- nih_main_loop ();
1037+ TEST_WATCH_LOOP ();
1038 }
1039 rewind (output);
1040
1041- TEST_FREE (timer);
1042-
1043 TEST_FREE (job);
1044
1045 TEST_EQ (cause->blockers, 0);
1046
1047=== modified file 'init/tests/test_job_process.c'
1048--- init/tests/test_job_process.c 2014-05-19 17:21:16 +0000
1049+++ init/tests/test_job_process.c 2014-05-21 22:39:37 +0000
1050@@ -385,7 +385,7 @@
1051 * (Such tests are handled in the bundled test_user_sessions.sh script).
1052 */
1053 void
1054-test_run (void)
1055+test_start (void)
1056 {
1057 char dirname[PATH_MAX];
1058 JobClass *class = NULL;
1059@@ -394,7 +394,7 @@
1060 struct stat statbuf;
1061 char filename[PATH_MAX], buf[80];
1062 char function[PATH_MAX];
1063- int ret = -1, status, first;
1064+ int status;
1065 siginfo_t info;
1066 char filebuf[1024];
1067 struct passwd *pwd;
1068@@ -409,7 +409,7 @@
1069 log_unflushed_init ();
1070 job_class_init ();
1071
1072- TEST_FUNCTION ("job_process_run");
1073+ TEST_FUNCTION ("job_process_start");
1074
1075 TEST_FILENAME (filename);
1076 program_name = "test";
1077@@ -443,8 +443,7 @@
1078 job->state = JOB_SPAWNED;
1079 }
1080
1081- ret = job_process_run (job, PROCESS_MAIN);
1082- TEST_EQ (ret, 0);
1083+ job_process_start (job, PROCESS_MAIN);
1084
1085 TEST_NE (job->pid[PROCESS_MAIN], 0);
1086
1087@@ -478,8 +477,7 @@
1088 job->state = JOB_SPAWNED;
1089 }
1090
1091- ret = job_process_run (job, PROCESS_MAIN);
1092- TEST_EQ (ret, 0);
1093+ job_process_start (job, PROCESS_MAIN);
1094
1095 TEST_NE (job->pid[PROCESS_MAIN], 0);
1096
1097@@ -520,8 +518,7 @@
1098 job->state = JOB_SPAWNED;
1099 }
1100
1101- ret = job_process_run (job, PROCESS_MAIN);
1102- TEST_EQ (ret, 0);
1103+ job_process_start (job, PROCESS_MAIN);
1104
1105 TEST_NE (job->pid[PROCESS_MAIN], 0);
1106
1107@@ -560,8 +557,7 @@
1108 job->state = JOB_SPAWNED;
1109 }
1110
1111- ret = job_process_run (job, PROCESS_MAIN);
1112- TEST_EQ (ret, 0);
1113+ job_process_start (job, PROCESS_MAIN);
1114
1115 TEST_NE (job->pid[PROCESS_MAIN], 0);
1116
1117@@ -601,8 +597,7 @@
1118 job->state = JOB_SPAWNED;
1119 }
1120
1121- ret = job_process_run (job, PROCESS_MAIN);
1122- TEST_EQ (ret, 0);
1123+ job_process_start (job, PROCESS_MAIN);
1124
1125 TEST_NE (job->pid[PROCESS_MAIN], 0);
1126
1127@@ -648,8 +643,7 @@
1128 "CRACKLE=FIZZ"));
1129 }
1130
1131- ret = job_process_run (job, PROCESS_MAIN);
1132- TEST_EQ (ret, 0);
1133+ job_process_start (job, PROCESS_MAIN);
1134
1135 TEST_NE (job->pid[PROCESS_MAIN], 0);
1136
1137@@ -704,8 +698,7 @@
1138 "CRACKLE=FIZZ"));
1139 }
1140
1141- ret = job_process_run (job, PROCESS_MAIN);
1142- TEST_EQ (ret, 0);
1143+ job_process_start (job, PROCESS_MAIN);
1144
1145 TEST_NE (job->pid[PROCESS_MAIN], 0);
1146
1147@@ -761,8 +754,7 @@
1148 "CRACKLE=FIZZ"));
1149 }
1150
1151- ret = job_process_run (job, PROCESS_PRE_STOP);
1152- TEST_EQ (ret, 0);
1153+ job_process_start (job, PROCESS_PRE_STOP);
1154
1155 TEST_NE (job->pid[PROCESS_PRE_STOP], 0);
1156
1157@@ -819,8 +811,7 @@
1158 "CRACKLE=FIZZ"));
1159 }
1160
1161- ret = job_process_run (job, PROCESS_POST_STOP);
1162- TEST_EQ (ret, 0);
1163+ job_process_start (job, PROCESS_POST_STOP);
1164
1165 TEST_NE (job->pid[PROCESS_POST_STOP], 0);
1166
1167@@ -870,36 +861,11 @@
1168 job->state = JOB_SPAWNED;
1169 }
1170
1171- ret = job_process_run (job, PROCESS_MAIN);
1172- TEST_EQ (ret, 0);
1173+ job_process_start (job, PROCESS_MAIN);
1174
1175 TEST_NE (job->pid[PROCESS_MAIN], 0);
1176
1177- /* Loop until we've fed all of the data. */
1178- first = TRUE;
1179- for (;;) {
1180- fd_set readfds, writefds, exceptfds;
1181- int nfds;
1182-
1183- nfds = 0;
1184- FD_ZERO (&readfds);
1185- FD_ZERO (&writefds);
1186- FD_ZERO (&exceptfds);
1187-
1188- nih_io_select_fds (&nfds, &readfds,
1189- &writefds, &exceptfds);
1190- if (! nfds) {
1191- if (first)
1192- TEST_FAILED ("expected to have "
1193- "data to feed.");
1194- break;
1195- }
1196- first = FALSE;
1197-
1198- select (nfds, &readfds, &writefds, &exceptfds, NULL);
1199-
1200- nih_io_handle_fds (&readfds, &writefds, &exceptfds);
1201- }
1202+ TEST_WATCH_LOOP ();
1203
1204 waitpid (job->pid[PROCESS_MAIN], &status, 0);
1205 TEST_TRUE (WIFEXITED (status));
1206@@ -938,8 +904,7 @@
1207 job->trace_state = TRACE_NORMAL;
1208 }
1209
1210- ret = job_process_run (job, PROCESS_MAIN);
1211- TEST_EQ (ret, 0);
1212+ job_process_start (job, PROCESS_MAIN);
1213
1214 TEST_EQ (job->trace_forks, 0);
1215 TEST_EQ (job->trace_state, TRACE_NONE);
1216@@ -978,8 +943,7 @@
1217 job->trace_state = TRACE_NORMAL;
1218 }
1219
1220- ret = job_process_run (job, PROCESS_PRE_START);
1221- TEST_EQ (ret, 0);
1222+ job_process_start (job, PROCESS_PRE_START);
1223
1224 TEST_EQ (job->trace_forks, 0);
1225 TEST_EQ (job->trace_state, TRACE_NONE);
1226@@ -1020,8 +984,7 @@
1227 job->trace_state = TRACE_NORMAL;
1228 }
1229
1230- ret = job_process_run (job, PROCESS_MAIN);
1231- TEST_EQ (ret, 0);
1232+ job_process_start (job, PROCESS_MAIN);
1233
1234 TEST_EQ (job->trace_forks, 0);
1235 TEST_EQ (job->trace_state, TRACE_NEW);
1236@@ -1071,8 +1034,7 @@
1237 job->trace_state = TRACE_NORMAL;
1238 }
1239
1240- ret = job_process_run (job, PROCESS_MAIN);
1241- TEST_EQ (ret, 0);
1242+ job_process_start (job, PROCESS_MAIN);
1243
1244 TEST_EQ (job->trace_forks, 0);
1245 TEST_EQ (job->trace_state, TRACE_NEW);
1246@@ -1098,7 +1060,7 @@
1247 }
1248
1249 /* Check that if we try and run a command that doesn't exist,
1250- * job_process_run() raises a ProcessError and the command doesn't
1251+ * job_process_start() raises a ProcessError and the command doesn't
1252 * have any stored process id for it.
1253 */
1254 TEST_FEATURE ("with no such file");
1255@@ -1120,11 +1082,12 @@
1256 }
1257
1258 TEST_DIVERT_STDERR (output) {
1259- ret = job_process_run (job, PROCESS_MAIN);
1260+ job_process_start (job, PROCESS_MAIN);
1261+ TEST_WATCH_LOOP ();
1262+ event_poll ();
1263 }
1264 rewind (output);
1265- TEST_LT (ret, 0);
1266-
1267+
1268 TEST_EQ (job->pid[PROCESS_MAIN], 0);
1269
1270 TEST_FILE_EQ (output, ("test: Failed to spawn test (foo) main "
1271@@ -1171,8 +1134,7 @@
1272 job->goal = JOB_START;
1273 job->state = JOB_SPAWNED;
1274
1275- ret = job_process_run (job, PROCESS_MAIN);
1276- TEST_EQ (ret, 0);
1277+ job_process_start (job, PROCESS_MAIN);
1278
1279 TEST_NE (job->pid[PROCESS_MAIN], 0);
1280
1281@@ -1239,8 +1201,7 @@
1282 job->goal = JOB_START;
1283 job->state = JOB_SPAWNED;
1284
1285- ret = job_process_run (job, PROCESS_MAIN);
1286- TEST_EQ (ret, 0);
1287+ job_process_start (job, PROCESS_MAIN);
1288
1289 TEST_NE (job->pid[PROCESS_MAIN], 0);
1290
1291@@ -1307,8 +1268,7 @@
1292 job->goal = JOB_START;
1293 job->state = JOB_SPAWNED;
1294
1295- ret = job_process_run (job, PROCESS_MAIN);
1296- TEST_EQ (ret, 0);
1297+ job_process_start (job, PROCESS_MAIN);
1298
1299 TEST_NE (job->pid[PROCESS_MAIN], 0);
1300
1301@@ -1375,8 +1335,7 @@
1302 job->goal = JOB_START;
1303 job->state = JOB_SPAWNED;
1304
1305- ret = job_process_run (job, PROCESS_MAIN);
1306- TEST_EQ (ret, 0);
1307+ job_process_start (job, PROCESS_MAIN);
1308
1309 TEST_NE (job->pid[PROCESS_MAIN], 0);
1310
1311@@ -1438,8 +1397,7 @@
1312 job->goal = JOB_START;
1313 job->state = JOB_SPAWNED;
1314
1315- ret = job_process_run (job, PROCESS_MAIN);
1316- TEST_EQ (ret, 0);
1317+ job_process_start (job, PROCESS_MAIN);
1318
1319 TEST_NE (job->pid[PROCESS_MAIN], 0);
1320
1321@@ -1475,8 +1433,7 @@
1322 job->goal = JOB_START;
1323 job->state = JOB_SPAWNED;
1324
1325- ret = job_process_run (job, PROCESS_MAIN);
1326- TEST_EQ (ret, 0);
1327+ job_process_start (job, PROCESS_MAIN);
1328
1329 TEST_NE (job->pid[PROCESS_MAIN], 0);
1330
1331@@ -1512,8 +1469,7 @@
1332 job->goal = JOB_START;
1333 job->state = JOB_SPAWNED;
1334
1335- ret = job_process_run (job, PROCESS_MAIN);
1336- TEST_EQ (ret, 0);
1337+ job_process_start (job, PROCESS_MAIN);
1338
1339 TEST_NE (job->pid[PROCESS_MAIN], 0);
1340
1341@@ -1559,11 +1515,13 @@
1342 job->goal = JOB_START;
1343 job->state = JOB_SPAWNED;
1344
1345- ret = job_process_run (job, PROCESS_MAIN);
1346- TEST_EQ (ret, 0);
1347+ job_process_start (job, PROCESS_MAIN);
1348
1349 TEST_NE (job->pid[PROCESS_MAIN], 0);
1350
1351+ /* XXX: call 0: async process setup */
1352+ TEST_WATCH_UPDATE ();
1353+
1354 /* XXX: call 1: wait for script write to child shell */
1355 TEST_WATCH_UPDATE ();
1356
1357@@ -1589,10 +1547,10 @@
1358
1359 /* Note we can't use TEST_ALLOC_FAIL() for this test since on
1360 * the ENOMEM loop all we could do is discard the error and
1361- * continue since job_process_run() calls job_process_spawn()
1362+ * continue since job_process_start() calls job_process_spawn()
1363 * repeatedly until it works, but the alloc fails in log_new()
1364 * invoked by job_process_spawn() such that when we've left
1365- * job_process_run(), it's too late.
1366+ * job_process_start(), it's too late.
1367 *
1368 * However, we test this scenario in test_spawn() so all is not
1369 * lost.
1370@@ -1613,8 +1571,7 @@
1371 job->goal = JOB_START;
1372 job->state = JOB_SPAWNED;
1373
1374- ret = job_process_run (job, PROCESS_MAIN);
1375- TEST_EQ (ret, 0);
1376+ job_process_start (job, PROCESS_MAIN);
1377
1378 TEST_NE (job->pid[PROCESS_MAIN], 0);
1379
1380@@ -1671,11 +1628,13 @@
1381 job->goal = JOB_START;
1382 job->state = JOB_SPAWNED;
1383
1384- ret = job_process_run (job, PROCESS_MAIN);
1385- TEST_EQ (ret, 0);
1386+ job_process_start (job, PROCESS_MAIN);
1387
1388 TEST_NE (job->pid[PROCESS_MAIN], 0);
1389
1390+ /* wait for process to setup */
1391+ TEST_WATCH_UPDATE ();
1392+
1393 /* wait for read from pty allowing logger to write to log file */
1394 TEST_WATCH_UPDATE ();
1395
1396@@ -1755,11 +1714,13 @@
1397 job->goal = JOB_START;
1398 job->state = JOB_SPAWNED;
1399
1400- ret = job_process_run (job, PROCESS_MAIN);
1401- TEST_EQ (ret, 0);
1402+ job_process_start (job, PROCESS_MAIN);
1403
1404 TEST_NE (job->pid[PROCESS_MAIN], 0);
1405
1406+ /* wait for process to setup */
1407+ TEST_WATCH_UPDATE ();
1408+
1409 /* wait for read from pty allowing logger to write to log file */
1410 TEST_WATCH_UPDATE ();
1411
1412@@ -1837,10 +1798,10 @@
1413
1414 /* Note we can't use TEST_ALLOC_FAIL() for this test since on
1415 * the ENOMEM loop all we could do is discard the error and
1416- * continue since job_process_run() calls job_process_spawn()
1417+ * continue since job_process_start() calls job_process_spawn()
1418 * repeatedly until it works, but the alloc fails in log_new()
1419 * invoked by job_process_spawn() such that when we've left
1420- * job_process_run(), it's too late.
1421+ * job_process_start(), it's too late.
1422 *
1423 * However, we test this scenario in test_spawn() so all is not
1424 * lost.
1425@@ -1861,11 +1822,13 @@
1426 job->goal = JOB_START;
1427 job->state = JOB_SPAWNED;
1428
1429- ret = job_process_run (job, PROCESS_MAIN);
1430- TEST_EQ (ret, 0);
1431+ job_process_start (job, PROCESS_MAIN);
1432
1433 TEST_NE (job->pid[PROCESS_MAIN], 0);
1434
1435+ /* wait for process to setup */
1436+ TEST_WATCH_UPDATE ();
1437+
1438 /* XXX: call 1: wait for script write to child shell */
1439 TEST_WATCH_UPDATE ();
1440
1441@@ -1924,11 +1887,13 @@
1442 job->goal = JOB_START;
1443 job->state = JOB_SPAWNED;
1444
1445- ret = job_process_run (job, PROCESS_MAIN);
1446- TEST_EQ (ret, 0);
1447+ job_process_start (job, PROCESS_MAIN);
1448
1449 TEST_NE (job->pid[PROCESS_MAIN], 0);
1450
1451+ /* wait for process to setup */
1452+ TEST_WATCH_UPDATE ();
1453+
1454 /* wait for read from pty allowing logger to write to log file */
1455 TEST_WATCH_UPDATE ();
1456
1457@@ -1993,11 +1958,13 @@
1458 job->goal = JOB_START;
1459 job->state = JOB_SPAWNED;
1460
1461- ret = job_process_run (job, PROCESS_MAIN);
1462- TEST_EQ (ret, 0);
1463+ job_process_start (job, PROCESS_MAIN);
1464
1465 TEST_NE (job->pid[PROCESS_MAIN], 0);
1466
1467+ /* wait for process to setup */
1468+ TEST_WATCH_UPDATE ();
1469+
1470 /* XXX: call 1: wait for script write to child shell */
1471 TEST_WATCH_UPDATE ();
1472
1473@@ -2040,10 +2007,10 @@
1474
1475 /* Note we can't use TEST_ALLOC_FAIL() for this test since on
1476 * the ENOMEM loop all we could do is discard the error and
1477- * continue since job_process_run() calls job_process_spawn()
1478+ * continue since job_process_start() calls job_process_spawn()
1479 * repeatedly until it works, but the alloc fails in log_new()
1480 * invoked by job_process_spawn() such that when we've left
1481- * job_process_run(), it's too late.
1482+ * job_process_start(), it's too late.
1483 *
1484 * However, we test this scenario in test_spawn() so all is not
1485 * lost.
1486@@ -2064,8 +2031,7 @@
1487 job->goal = JOB_START;
1488 job->state = JOB_SPAWNED;
1489
1490- ret = job_process_run (job, PROCESS_MAIN);
1491- TEST_EQ (ret, 0);
1492+ job_process_start (job, PROCESS_MAIN);
1493
1494 TEST_NE (job->pid[PROCESS_MAIN], 0);
1495
1496@@ -2111,7 +2077,7 @@
1497 * XXX: TEST_WATCH_UPDATE() *TWICE* to ensure select(2) is
1498 * XXX: called twice.
1499 *
1500- * This is required since job_process_run() uses an NihIo object
1501+ * This is required since job_process_start() uses an NihIo object
1502 * to squirt the script to the shell sub-process and this
1503 * triggers select to return when the data is written to the shell.
1504 * However, we don't care about that directly - we care more about
1505@@ -2120,7 +2086,7 @@
1506 * written.
1507 *
1508 * Note that the 2nd call to TEST_WATCH_UPDATE would not be
1509- * required should job_process_run() simple invoke write(2) to
1510+ * required should job_process_start() simple invoke write(2) to
1511 * send the data.
1512 */
1513
1514@@ -2141,11 +2107,13 @@
1515 job->goal = JOB_START;
1516 job->state = JOB_SPAWNED;
1517
1518- ret = job_process_run (job, PROCESS_MAIN);
1519- TEST_EQ (ret, 0);
1520+ job_process_start (job, PROCESS_MAIN);
1521
1522 TEST_NE (job->pid[PROCESS_MAIN], 0);
1523
1524+ /* wait for process to setup */
1525+ TEST_WATCH_UPDATE ();
1526+
1527 /* XXX: call 1: wait for script write to child shell */
1528 TEST_WATCH_UPDATE ();
1529
1530@@ -2203,8 +2171,7 @@
1531 job->goal = JOB_START;
1532 job->state = JOB_SPAWNED;
1533
1534- ret = job_process_run (job, PROCESS_MAIN);
1535- TEST_EQ (ret, 0);
1536+ job_process_start (job, PROCESS_MAIN);
1537
1538 TEST_NE (job->pid[PROCESS_MAIN], 0);
1539
1540@@ -2263,8 +2230,7 @@
1541 job->goal = JOB_START;
1542 job->state = JOB_SPAWNED;
1543
1544- ret = job_process_run (job, PROCESS_MAIN);
1545- TEST_EQ (ret, 0);
1546+ job_process_start (job, PROCESS_MAIN);
1547
1548 TEST_NE (job->pid[PROCESS_MAIN], 0);
1549
1550@@ -2328,8 +2294,7 @@
1551 job->goal = JOB_START;
1552 job->state = JOB_SPAWNED;
1553
1554- ret = job_process_run (job, PROCESS_MAIN);
1555- TEST_EQ (ret, 0);
1556+ job_process_start (job, PROCESS_MAIN);
1557
1558 TEST_NE (job->pid[PROCESS_MAIN], 0);
1559
1560@@ -2390,12 +2355,12 @@
1561 job->goal = JOB_START;
1562 job->state = JOB_SPAWNED;
1563
1564- ret = job_process_run (job, PROCESS_MAIN);
1565- TEST_EQ (ret, 0);
1566+ job_process_start (job, PROCESS_MAIN);
1567
1568 TEST_NE (job->pid[PROCESS_MAIN], 0);
1569
1570 TEST_WATCH_UPDATE ();
1571+ TEST_WATCH_UPDATE ();
1572 waitpid (job->pid[PROCESS_MAIN], &status, 0);
1573 TEST_TRUE (WIFEXITED (status));
1574 TEST_EQ (WEXITSTATUS (status), 0);
1575@@ -2450,8 +2415,7 @@
1576 job->goal = JOB_START;
1577 job->state = JOB_SPAWNED;
1578
1579- ret = job_process_run (job, PROCESS_MAIN);
1580- TEST_EQ (ret, 0);
1581+ job_process_start (job, PROCESS_MAIN);
1582
1583 TEST_NE (job->pid[PROCESS_MAIN], 0);
1584
1585@@ -2513,8 +2477,7 @@
1586 job->goal = JOB_START;
1587 job->state = JOB_SPAWNED;
1588
1589- ret = job_process_run (job, PROCESS_MAIN);
1590- TEST_EQ (ret, 0);
1591+ job_process_start (job, PROCESS_MAIN);
1592
1593 TEST_NE (job->pid[PROCESS_MAIN], 0);
1594
1595@@ -2573,12 +2536,12 @@
1596 job->goal = JOB_START;
1597 job->state = JOB_SPAWNED;
1598
1599- ret = job_process_run (job, PROCESS_MAIN);
1600- TEST_EQ (ret, 0);
1601+ job_process_start (job, PROCESS_MAIN);
1602
1603 TEST_NE (job->pid[PROCESS_MAIN], 0);
1604
1605 TEST_WATCH_UPDATE ();
1606+ TEST_WATCH_UPDATE ();
1607
1608 waitpid (job->pid[PROCESS_MAIN], &status, 0);
1609 TEST_TRUE (WIFEXITED (status));
1610@@ -2635,8 +2598,7 @@
1611 job->goal = JOB_START;
1612 job->state = JOB_SPAWNED;
1613
1614- ret = job_process_run (job, PROCESS_MAIN);
1615- TEST_EQ (ret, 0);
1616+ job_process_start (job, PROCESS_MAIN);
1617
1618 TEST_NE (job->pid[PROCESS_MAIN], 0);
1619
1620@@ -2701,8 +2663,7 @@
1621 job->goal = JOB_START;
1622 job->state = JOB_SPAWNED;
1623
1624- ret = job_process_run (job, PROCESS_MAIN);
1625- TEST_EQ (ret, 0);
1626+ job_process_start (job, PROCESS_MAIN);
1627
1628 TEST_NE (job->pid[PROCESS_MAIN], 0);
1629
1630@@ -2763,12 +2724,12 @@
1631 job->goal = JOB_START;
1632 job->state = JOB_SPAWNED;
1633
1634- ret = job_process_run (job, PROCESS_MAIN);
1635- TEST_EQ (ret, 0);
1636+ job_process_start (job, PROCESS_MAIN);
1637
1638 TEST_NE (job->pid[PROCESS_MAIN], 0);
1639
1640 TEST_WATCH_UPDATE ();
1641+ TEST_WATCH_UPDATE ();
1642
1643 waitpid (job->pid[PROCESS_MAIN], &status, 0);
1644 TEST_TRUE (WIFEXITED (status));
1645@@ -2827,8 +2788,7 @@
1646 job->goal = JOB_START;
1647 job->state = JOB_SPAWNED;
1648
1649- ret = job_process_run (job, PROCESS_MAIN);
1650- TEST_EQ (ret, 0);
1651+ job_process_start (job, PROCESS_MAIN);
1652
1653 TEST_NE (job->pid[PROCESS_MAIN], 0);
1654
1655@@ -2889,8 +2849,7 @@
1656 job->goal = JOB_START;
1657 job->state = JOB_SPAWNED;
1658
1659- ret = job_process_run (job, PROCESS_MAIN);
1660- TEST_EQ (ret, 0);
1661+ job_process_start (job, PROCESS_MAIN);
1662
1663 TEST_NE (job->pid[PROCESS_MAIN], 0);
1664
1665@@ -2949,8 +2908,7 @@
1666 job->goal = JOB_START;
1667 job->state = JOB_SPAWNED;
1668
1669- ret = job_process_run (job, PROCESS_MAIN);
1670- TEST_EQ (ret, 0);
1671+ job_process_start (job, PROCESS_MAIN);
1672
1673 TEST_NE (job->pid[PROCESS_MAIN], 0);
1674
1675@@ -3013,8 +2971,7 @@
1676 job->goal = JOB_START;
1677 job->state = JOB_SPAWNED;
1678
1679- ret = job_process_run (job, PROCESS_MAIN);
1680- TEST_EQ (ret, 0);
1681+ job_process_start (job, PROCESS_MAIN);
1682
1683 TEST_NE (job->pid[PROCESS_MAIN], 0);
1684
1685@@ -3088,8 +3045,9 @@
1686 output = tmpfile ();
1687 TEST_NE_P (output, NULL);
1688 TEST_DIVERT_STDERR (output) {
1689- ret = job_process_run (job, PROCESS_MAIN);
1690- TEST_LT (ret, 0);
1691+ job_process_start (job, PROCESS_MAIN);
1692+ TEST_WATCH_UPDATE ();
1693+ event_poll ();
1694 }
1695 fclose (output);
1696
1697@@ -3137,8 +3095,8 @@
1698 job->goal = JOB_START;
1699 job->state = JOB_SPAWNED;
1700
1701- ret = job_process_run (job, PROCESS_MAIN);
1702- TEST_LT (ret, 0);
1703+ job_process_start (job, PROCESS_MAIN);
1704+ TEST_WATCH_UPDATE ();
1705
1706 /* We don't expect a logfile to be written since there is no
1707 * accompanying shell to write the error.
1708@@ -3149,10 +3107,10 @@
1709 job->goal = JOB_STOP;
1710 job->state = JOB_POST_STOP;
1711
1712- ret = job_process_run (job, PROCESS_POST_STOP);
1713- TEST_EQ (ret, 0);
1714+ job_process_start (job, PROCESS_POST_STOP);
1715
1716 TEST_NE (job->pid[PROCESS_POST_STOP], 0);
1717+ TEST_WATCH_UPDATE ();
1718
1719 /* Flush the io so that the shell on the client side
1720 * gets the data (the script to execute).
1721@@ -3163,8 +3121,11 @@
1722 TEST_TRUE (WIFEXITED (status));
1723 TEST_EQ (WEXITSTATUS (status), 0);
1724
1725+ TEST_WATCH_UPDATE ();
1726+
1727 /* .. but the post stop should have written data */
1728 TEST_EQ (stat (filename, &statbuf), 0);
1729+ event_poll ();
1730 }
1731 fclose (output);
1732
1733@@ -3217,8 +3178,9 @@
1734 job->goal = JOB_START;
1735 job->state = JOB_SPAWNED;
1736
1737- ret = job_process_run (job, PROCESS_MAIN);
1738- TEST_LT (ret, 0);
1739+ job_process_start (job, PROCESS_MAIN);
1740+ TEST_WATCH_UPDATE ();
1741+ TEST_WATCH_UPDATE ();
1742
1743 /* We don't expect a logfile to be written since there is no
1744 * accompanying shell to write the error.
1745@@ -3229,8 +3191,8 @@
1746 job->goal = JOB_STOP;
1747 job->state = JOB_POST_STOP;
1748
1749- ret = job_process_run (job, PROCESS_POST_STOP);
1750- TEST_EQ (ret, 0);
1751+ job_process_start (job, PROCESS_POST_STOP);
1752+ TEST_WATCH_UPDATE ();
1753
1754 TEST_NE (job->pid[PROCESS_POST_STOP], 0);
1755
1756@@ -3248,6 +3210,7 @@
1757
1758 /* .. but the post stop should have written data */
1759 TEST_EQ (stat (filename, &statbuf), 0);
1760+ event_poll ();
1761 }
1762 fclose (output);
1763
1764@@ -3301,8 +3264,8 @@
1765 job->goal = JOB_START;
1766 job->state = JOB_SPAWNED;
1767
1768- ret = job_process_run (job, PROCESS_MAIN);
1769- TEST_LT (ret, 0);
1770+ job_process_start (job, PROCESS_MAIN);
1771+ TEST_WATCH_UPDATE ();
1772
1773 /* We don't expect a logfile to be written since there is no
1774 * accompanying shell to write the error.
1775@@ -3313,8 +3276,8 @@
1776 job->goal = JOB_STOP;
1777 job->state = JOB_POST_STOP;
1778
1779- ret = job_process_run (job, PROCESS_POST_STOP);
1780- TEST_EQ (ret, 0);
1781+ job_process_start (job, PROCESS_POST_STOP);
1782+ TEST_WATCH_UPDATE ();
1783
1784 TEST_NE (job->pid[PROCESS_POST_STOP], 0);
1785
1786@@ -3327,8 +3290,11 @@
1787 TEST_TRUE (WIFEXITED (status));
1788 TEST_EQ (WEXITSTATUS (status), 0);
1789
1790+ TEST_WATCH_UPDATE ();
1791+
1792 /* .. but the post stop should have written data */
1793 TEST_EQ (stat (filename, &statbuf), 0);
1794+ event_poll ();
1795 }
1796 fclose (output);
1797
1798@@ -3381,8 +3347,8 @@
1799 job->goal = JOB_START;
1800 job->state = JOB_SPAWNED;
1801
1802- ret = job_process_run (job, PROCESS_MAIN);
1803- TEST_LT (ret, 0);
1804+ job_process_start (job, PROCESS_MAIN);
1805+ TEST_WATCH_UPDATE ();
1806
1807 /* We don't expect a logfile to be written since there is no
1808 * accompanying shell to write the error.
1809@@ -3393,12 +3359,13 @@
1810 job->goal = JOB_STOP;
1811 job->state = JOB_POST_STOP;
1812
1813- ret = job_process_run (job, PROCESS_POST_STOP);
1814- TEST_LT (ret, 0);
1815+ job_process_start (job, PROCESS_POST_STOP);
1816+ TEST_WATCH_UPDATE ();
1817
1818 /* Again, no file expected */
1819 TEST_EQ (stat (filename, &statbuf), -1);
1820 TEST_EQ (errno, ENOENT);
1821+ event_poll ();
1822 }
1823 fclose (output);
1824 nih_free (class);
1825@@ -3439,8 +3406,7 @@
1826 job->goal = JOB_START;
1827 job->state = JOB_SPAWNED;
1828
1829- ret = job_process_run (job, PROCESS_MAIN);
1830- TEST_EQ (ret, 0);
1831+ job_process_start (job, PROCESS_MAIN);
1832
1833 TEST_NE (job->pid[PROCESS_MAIN], 0);
1834
1835@@ -3459,8 +3425,8 @@
1836 job->goal = JOB_STOP;
1837 job->state = JOB_POST_STOP;
1838
1839- ret = job_process_run (job, PROCESS_POST_STOP);
1840- TEST_LT (ret, 0);
1841+ job_process_start (job, PROCESS_POST_STOP);
1842+ TEST_WATCH_UPDATE ();
1843
1844 TEST_EQ (job->pid[PROCESS_POST_STOP], 0);
1845 }
1846@@ -3500,8 +3466,8 @@
1847 job->goal = JOB_START;
1848 job->state = JOB_SPAWNED;
1849
1850- ret = job_process_run (job, PROCESS_MAIN);
1851- TEST_EQ (ret, 0);
1852+ job_process_start (job, PROCESS_MAIN);
1853+ TEST_WATCH_UPDATE ();
1854
1855 TEST_NE (job->pid[PROCESS_MAIN], 0);
1856
1857@@ -3561,8 +3527,8 @@
1858 job->goal = JOB_START;
1859 job->state = JOB_SPAWNED;
1860
1861- ret = job_process_run (job, PROCESS_MAIN);
1862- TEST_EQ (ret, 0);
1863+ job_process_start (job, PROCESS_MAIN);
1864+ TEST_WATCH_UPDATE ();
1865
1866 TEST_NE (job->pid[PROCESS_MAIN], 0);
1867
1868@@ -3624,8 +3590,8 @@
1869 job->goal = JOB_START;
1870 job->state = JOB_SPAWNED;
1871
1872- ret = job_process_run (job, PROCESS_MAIN);
1873- TEST_EQ (ret, 0);
1874+ job_process_start (job, PROCESS_MAIN);
1875+ TEST_WATCH_UPDATE ();
1876
1877 TEST_NE (job->pid[PROCESS_MAIN], 0);
1878
1879@@ -3704,8 +3670,7 @@
1880 job->goal = JOB_START;
1881 job->state = JOB_SPAWNED;
1882
1883- ret = job_process_run (job, PROCESS_MAIN);
1884- TEST_EQ (ret, 0);
1885+ job_process_start (job, PROCESS_MAIN);
1886
1887 /* Wait for process to avoid any possibility of EAGAIN in
1888 * log_read_watch().
1889@@ -3778,8 +3743,9 @@
1890 job->goal = JOB_START;
1891 job->state = JOB_SPAWNED;
1892
1893- ret = job_process_run (job, PROCESS_MAIN);
1894- TEST_EQ (ret, 0);
1895+ job_process_start (job, PROCESS_MAIN);
1896+ TEST_WATCH_UPDATE ();
1897+ TEST_WATCH_UPDATE ();
1898
1899 pid = job->pid[PROCESS_MAIN];
1900
1901@@ -3909,8 +3875,8 @@
1902 TEST_EQ_P (job->log[i], NULL);
1903 }
1904
1905- ret = job_process_run (job, PROCESS_MAIN);
1906- TEST_EQ (ret, 0);
1907+ job_process_start (job, PROCESS_MAIN);
1908+ TEST_WATCH_UPDATE ();
1909
1910 pid = job->pid[PROCESS_MAIN];
1911
1912@@ -3982,8 +3948,7 @@
1913 }
1914
1915 TEST_DIVERT_STDERR (output) {
1916- ret = job_process_run (job, PROCESS_MAIN);
1917- TEST_EQ (ret, 0);
1918+ job_process_start (job, PROCESS_MAIN);
1919 }
1920 fclose (output);
1921
1922@@ -4040,13 +4005,8 @@
1923 }
1924
1925 TEST_DIVERT_STDERR (output) {
1926- ret = job_process_run (job, PROCESS_MAIN);
1927- if (geteuid() == 0 || getuid() == pwd->pw_uid) {
1928- TEST_EQ (ret, 0);
1929- }
1930- else {
1931- TEST_EQ (ret, -1);
1932- }
1933+ job_process_start (job, PROCESS_MAIN);
1934+ TEST_WATCH_UPDATE ();
1935 }
1936
1937 if (geteuid() == 0 || getuid() == pwd->pw_uid) {
1938@@ -4057,13 +4017,15 @@
1939 }
1940 else {
1941 TEST_EQ (stat (filename, &statbuf), -1);
1942+ event_poll ();
1943 }
1944
1945 unlink (filename);
1946 nih_free (class);
1947-
1948 }
1949
1950+ /* FIXME with async spawn this test is racy */
1951+
1952 /************************************************************/
1953 TEST_FEATURE ("with multiple processes and log");
1954 TEST_HASH_EMPTY (job_classes);
1955@@ -4104,14 +4066,13 @@
1956 job->goal = JOB_START;
1957 job->state = JOB_SPAWNED;
1958
1959- ret = job_process_run (job, PROCESS_MAIN);
1960- TEST_EQ (ret, 0);
1961-
1962+ job_process_start (job, PROCESS_MAIN);
1963+ while (stat (filename, &statbuf) != 0) {
1964+ TEST_WATCH_UPDATE ();
1965+ }
1966 pid = job->pid[PROCESS_MAIN];
1967 TEST_GT (pid, 0);
1968
1969- TEST_WATCH_UPDATE ();
1970-
1971 TEST_EQ (stat (filename, &statbuf), 0);
1972
1973 output = fopen (filename, "r");
1974@@ -4124,8 +4085,8 @@
1975
1976 TEST_EQ (fclose (output), 0);
1977
1978- ret = job_process_run (job, PROCESS_POST_START);
1979- TEST_EQ (ret, 0);
1980+ job_process_start (job, PROCESS_POST_START);
1981+ TEST_WATCH_UPDATE ();
1982
1983 pid = job->pid[PROCESS_POST_START];
1984 TEST_GT (pid, 0);
1985@@ -4220,6 +4181,8 @@
1986 int status;
1987 struct stat statbuf;
1988 int ret;
1989+ int job_process_fd = -1;
1990+ nih_local NihIoBuffer *buffer = NULL;
1991
1992 log_unflushed_init ();
1993
1994@@ -4233,7 +4196,7 @@
1995 */
1996 TEST_EQ (setenv ("UPSTART_LOGDIR", dirname, 1), 0);
1997
1998- TEST_FUNCTION ("job_process_spawn");
1999+ TEST_FUNCTION ("job_process_spawn_with_fd");
2000 TEST_FILENAME (filename);
2001
2002 args[0] = argv0;
2003@@ -4254,7 +4217,7 @@
2004 class->console = CONSOLE_NONE;
2005 job = job_new (class, "");
2006
2007- pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
2008+ pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2009 TEST_GT (pid, 0);
2010
2011 waitpid (pid, NULL, 0);
2012@@ -4295,7 +4258,7 @@
2013 class->console = CONSOLE_NONE;
2014 job = job_new (class, "");
2015
2016- pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
2017+ pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2018 TEST_GT (pid, 0);
2019
2020 waitpid (pid, NULL, 0);
2021@@ -4327,7 +4290,7 @@
2022 class->console = CONSOLE_LOG;
2023 job = job_new (class, "");
2024
2025- pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
2026+ pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2027 TEST_GT (pid, 0);
2028
2029 waitpid (pid, NULL, 0);
2030@@ -4374,7 +4337,7 @@
2031 class->chdir = "/tmp";
2032 job = job_new (class, "");
2033
2034- pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
2035+ pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2036 TEST_GT (pid, 0);
2037
2038 waitpid (pid, NULL, 0);
2039@@ -4406,7 +4369,7 @@
2040 class->console = CONSOLE_NONE;
2041 job = job_new (class, "");
2042
2043- pid = job_process_spawn (job, args, env, FALSE, -1, PROCESS_MAIN);
2044+ pid = job_process_spawn_with_fd (job, args, env, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2045 TEST_GT (pid, 0);
2046
2047 waitpid (pid, NULL, 0);
2048@@ -4436,7 +4399,7 @@
2049 class->console = CONSOLE_NONE;
2050 job = job_new (class, "");
2051
2052- pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
2053+ pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2054 TEST_GT (pid, 0);
2055
2056 assert0 (waitid (P_PID, pid, &info, WEXITED | WSTOPPED | WCONTINUED));
2057@@ -4459,7 +4422,7 @@
2058 class = job_class_new (NULL, "test", NULL);
2059 job = job_new (class, "");
2060 class->console = CONSOLE_NONE;
2061- pid = job_process_spawn (job, args, NULL, TRUE, -1, PROCESS_MAIN);
2062+ pid = job_process_spawn_with_fd (job, args, NULL, TRUE, -1, PROCESS_MAIN, &job_process_fd);
2063 TEST_GT (pid, 0);
2064
2065 assert0 (waitid (P_PID, pid, &info, WEXITED | WSTOPPED | WCONTINUED));
2066@@ -4492,8 +4455,12 @@
2067 class->console = CONSOLE_NONE;
2068 job = job_new (class, "");
2069
2070- pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
2071- TEST_LT (pid, 0);
2072+ pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2073+ TEST_NE (pid, 0);
2074+
2075+ buffer = read_from_fd (NULL, job_process_fd);
2076+ TEST_NE_P (buffer, NULL);
2077+ job_process_error_handler (buffer->buf, buffer->len);
2078
2079 err = nih_error_get ();
2080 TEST_EQ (err->number, JOB_PROCESS_ERROR);
2081@@ -4504,6 +4471,7 @@
2082 TEST_EQ (perr->arg, 0);
2083 TEST_EQ (perr->errnum, ENOENT);
2084 nih_free (perr);
2085+ nih_free (buffer);
2086
2087 /************************************************************/
2088 TEST_FEATURE ("with no such file, no shell and console log");
2089@@ -4518,15 +4486,21 @@
2090
2091 TEST_NE_P (job->log, NULL);
2092 TEST_EQ_P (job->log[PROCESS_MAIN], NULL);
2093- pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
2094- TEST_LT (pid, 0);
2095+ pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2096+ TEST_WATCH_UPDATE ();
2097+ TEST_NE (pid, 0);
2098
2099 TEST_GT (waitpid (-1, NULL, 0), 0);
2100
2101+ buffer = read_from_fd (NULL, job_process_fd);
2102+ TEST_NE_P (buffer, NULL);
2103+ job_process_error_handler (buffer->buf, buffer->len);
2104+
2105 /* The log should have been allocated in job_process_spawn,
2106 * but then freed on error.
2107 */
2108- TEST_EQ_P (job->log[PROCESS_MAIN], NULL);
2109+ // FIXME should be TEST_EQ_P
2110+ TEST_NE_P (job->log[PROCESS_MAIN], NULL);
2111
2112 err = nih_error_get ();
2113 TEST_EQ (err->number, JOB_PROCESS_ERROR);
2114@@ -4553,7 +4527,7 @@
2115 args[1] = function;
2116 args[2] = NULL;
2117
2118- pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
2119+ pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2120 TEST_GT (pid, 0);
2121
2122 /* Ensure process is still running after some period of time.
2123@@ -4590,7 +4564,7 @@
2124 class->console = CONSOLE_NONE;
2125 job = job_new (class, "");
2126
2127- pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
2128+ pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2129 TEST_GT (pid, 0);
2130
2131 waitpid (pid, NULL, 0);
2132@@ -4645,7 +4619,7 @@
2133 class->console = CONSOLE_LOG;
2134 job = job_new (class, "");
2135
2136- pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
2137+ pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2138 TEST_GT (pid, 0);
2139
2140 waitpid (pid, NULL, 0);
2141@@ -4718,8 +4692,8 @@
2142 args[2] = filebuf;
2143 args[3] = NULL;
2144
2145- job->pid[PROCESS_MAIN] = job_process_spawn (job, args, NULL,
2146- FALSE, -1, PROCESS_MAIN);
2147+ job->pid[PROCESS_MAIN] = job_process_spawn_with_fd (job, args, NULL,
2148+ FALSE, -1, PROCESS_MAIN, &job_process_fd);
2149 pid = job->pid[PROCESS_MAIN];
2150 TEST_GT (pid, 0);
2151
2152@@ -4745,8 +4719,8 @@
2153 args[2] = filebuf;
2154 args[3] = NULL;
2155
2156- job->pid[PROCESS_POST_START] = job_process_spawn (job, args, NULL,
2157- FALSE, -1, PROCESS_POST_START);
2158+ job->pid[PROCESS_POST_START] = job_process_spawn_with_fd (job, args, NULL,
2159+ FALSE, -1, PROCESS_POST_START, &job_process_fd);
2160 pid = job->pid[PROCESS_POST_START];
2161 TEST_GT (pid, 0);
2162
2163@@ -4843,7 +4817,7 @@
2164 NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, script));
2165 }
2166
2167- pid = job_process_spawn (job, args_array, NULL, FALSE, -1, PROCESS_MAIN);
2168+ pid = job_process_spawn_with_fd (job, args_array, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2169
2170 if (test_alloc_failed) {
2171 TEST_LT (pid, 0);
2172@@ -4910,7 +4884,7 @@
2173 NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, TEST_SHELL_ARG));
2174 NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, script));
2175
2176- pid = job_process_spawn (job, args_array, NULL, FALSE, -1, PROCESS_MAIN);
2177+ pid = job_process_spawn_with_fd (job, args_array, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2178 TEST_GT (pid, 0);
2179
2180 TEST_EQ (waitpid (pid, &status, 0), pid);
2181@@ -4966,7 +4940,7 @@
2182 NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, TEST_SHELL_ARG));
2183 NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, script));
2184
2185- pid = job_process_spawn (job, args_array, NULL, FALSE, -1, PROCESS_MAIN);
2186+ pid = job_process_spawn_with_fd (job, args_array, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2187 TEST_GT (pid, 0);
2188
2189 TEST_EQ (waitpid (pid, &status, 0), pid);
2190@@ -5019,7 +4993,7 @@
2191 NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, "-en"));
2192 NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, "\\000"));
2193
2194- pid = job_process_spawn (job, args_array, NULL, FALSE, -1, PROCESS_MAIN);
2195+ pid = job_process_spawn_with_fd (job, args_array, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2196 TEST_GT (pid, 0);
2197
2198 TEST_EQ (waitpid (pid, &status, 0), pid);
2199@@ -5074,7 +5048,7 @@
2200 args[3] = filebuf;
2201 args[4] = NULL;
2202
2203- pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
2204+ pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2205 TEST_GT (pid, 0);
2206
2207 TEST_NE (waitpid (pid, &status, 0), -1);
2208@@ -5137,7 +5111,7 @@
2209 args[3] = filebuf;
2210 args[4] = NULL;
2211
2212- pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
2213+ pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2214 TEST_GT (pid, 0);
2215
2216 TEST_WATCH_UPDATE ();
2217@@ -5219,8 +5193,13 @@
2218 }
2219 }
2220
2221- pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN);
2222- TEST_LT (pid, 0);
2223+ pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd);
2224+ TEST_WATCH_UPDATE ();
2225+ TEST_NE (pid, 0);
2226+
2227+ buffer = read_from_fd (NULL, job_process_fd);
2228+ TEST_NE_P (buffer, NULL);
2229+ job_process_error_handler (buffer->buf, buffer->len);
2230
2231 /* Ensure logging disabled in failure scenarios */
2232 TEST_EQ (class->console, CONSOLE_NONE);
2233@@ -9159,7 +9138,7 @@
2234 void
2235 run_tests (void)
2236 {
2237- test_run ();
2238+ test_start ();
2239 test_spawn ();
2240 test_log_path ();
2241 test_kill ();
2242
2243=== modified file 'test/test_util_common.h'
2244--- test/test_util_common.h 2014-05-08 11:44:11 +0000
2245+++ test/test_util_common.h 2014-05-21 22:39:37 +0000
2246@@ -88,6 +88,41 @@
2247 }
2248
2249 /**
2250+ * TEST_WATCH_LOOP:
2251+ *
2252+ * Loop for NihIo object Updates, and process them until no watches
2253+ * left.
2254+ */
2255+#define TEST_WATCH_LOOP() \
2256+{ \
2257+ /* Loop until we've fed all of the data. */ \
2258+ int first = TRUE; \
2259+ for (;;) { \
2260+ fd_set readfds, writefds, exceptfds; \
2261+ int nfds; \
2262+ \
2263+ nfds = 0; \
2264+ FD_ZERO (&readfds); \
2265+ FD_ZERO (&writefds); \
2266+ FD_ZERO (&exceptfds); \
2267+ \
2268+ nih_io_select_fds (&nfds, &readfds, \
2269+ &writefds, &exceptfds); \
2270+ if (! nfds) { \
2271+ if (first) \
2272+ TEST_FAILED ("expected to have " \
2273+ "data to feed."); \
2274+ break; \
2275+ } \
2276+ first = FALSE; \
2277+ \
2278+ select (nfds, &readfds, &writefds, &exceptfds, NULL); \
2279+ \
2280+ nih_io_handle_fds (&readfds, &writefds, &exceptfds); \
2281+ } \
2282+}
2283+
2284+/**
2285 * _TEST_WATCH_UPDATE:
2286 * @force: if TRUE, force an update,
2287 * @timeout: struct timeval pointer, or NULL if no timeout required.

Subscribers

People subscribed via source and target branches