Merge lp:~xnox/upstart/shrink-notifications into lp:upstart

Proposed by Dimitri John Ledkov
Status: Merged
Merged at revision: 1645
Proposed branch: lp:~xnox/upstart/shrink-notifications
Merge into: lp:upstart
Diff against target: 1622 lines (+778/-166)
7 files modified
ChangeLog (+15/-0)
init/job.c (+0/-5)
init/job_process.c (+13/-6)
init/job_process.h (+4/-0)
init/tests/test_job_process.c (+512/-148)
test/test_util_common.c (+9/-4)
util/tests/test_initctl.c (+225/-3)
To merge this branch: bzr merge lp:~xnox/upstart/shrink-notifications
Reviewer Review Type Date Requested Status
James Hunt Needs Fixing
Review via email: mp+225200@code.launchpad.net
To post a comment you must log in.
Revision history for this message
James Hunt (jamesodhunt) wrote :

As discussed, we should not be disabling tests so need to get to the bottom of the failures.

review: Needs Fixing
1641. By Dimitri John Ledkov

Wait for the right pid to exit, reset main-loop state between tests

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

Thanks for pointing out that the test-harness is broken and not the test. And hence the test fails because of bad environment.

* added helpers to install handlers, which can be reset with the TEST_RESET_MAIN_LOOP()
* realized that i need to pass the desired pid to the exit handler, instead of simply quiting on the first one
* modified affected tests to use main loop and properly clean-up environment before and after it self

All tests pass now \o/

Revision history for this message
James Hunt (jamesodhunt) wrote :

Thanks! However, test_job_process.c is still failing for me:

#2 0x0000000000433a2d in test_start () at tests/test_job_process.c:4160
4160 TEST_FILE_END (output);

Also, re-exec is failing occasionally for me with EBADF thrown by nih_io_reopen().

Also, could you remove that stale comment in job_process_close_handler().

review: Needs Fixing
1642. By Dimitri John Ledkov

Catch up trunk

1643. By Dimitri John Ledkov

Reduce races in 'with multiple processes and log' test by waiting for sufficiently large log file to be written.

1644. By Dimitri John Ledkov

remove stale comment

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

> Thanks! However, test_job_process.c is still failing for me:
>
> #2 0x0000000000433a2d in test_start () at tests/test_job_process.c:4160
> 4160 TEST_FILE_END (output);
>

That test is racy since async branch introduction and has a comment to denote as such. I've not committed a couple of guards to reduce spurious failures of this test, by waiting for sufficiently large enough log file to be written.

> Also, re-exec is failing occasionally for me with EBADF thrown by
> nih_io_reopen().
>

=/

> Also, could you remove that stale comment in job_process_close_handler().

Done.

Revision history for this message
James Hunt (jamesodhunt) wrote :

test_job_process.c is frequently hanging for me and there are a few instances spinning at 100% CPU in the background.

review: Needs Fixing
1645. By Dimitri John Ledkov

Merge trunk

1646. By Dimitri John Ledkov

100 interations pass

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

Backed out jodh's merged tests.
Made tests resilient to tests (pass 100+ iterations).

Fixed races:
- sigchild ariving, before read handler is called

Fixed aborts:
- due to multiple io reads, since process_fd pipe was not cleared
- job_process_error_handler returning EILSEQ
- double freeing io, when read handler is called before close handles

Revision history for this message
James Hunt (jamesodhunt) wrote :

Still racy I'm afraid:

not ok 48 - with single-line command running an invalid command, then a 1-line post-stop script
        wrong value for child_exit_status[1], expected 255 got 0
        at tests/test_job_process.c:3193 (test_start).
Aborted (core dumped)
ERROR: failed on iteration 6

#2 0x0000000000428c92 in test_start () at tests/test_job_process.c:3193
3193 TEST_EQ (child_exit_status[1], 255);
(gdb) p child_exit_status[1]
$1 = 0
(gdb)

review: Needs Fixing
Revision history for this message
Dimitri John Ledkov (xnox) wrote :

> Still racy I'm afraid:
>
> not ok 48 - with single-line command running an invalid command, then a 1-line
> post-stop script
> wrong value for child_exit_status[1], expected 255 got 0
> at tests/test_job_process.c:3193 (test_start).
> Aborted (core dumped)
> ERROR: failed on iteration 6
>
> #2 0x0000000000428c92 in test_start () at tests/test_job_process.c:3193
> 3193 TEST_EQ (child_exit_status[1], 255);
> (gdb) p child_exit_status[1]
> $1 = 0
> (gdb)

It is better than it was before.

What about review of the actual code changes? Do you approve those?

Revision history for this message
James Hunt (jamesodhunt) wrote :

I don't understand the change you've made to job_process_handler():

=== modified file 'init/job_process.c'
--- init/job_process.c 2014-07-08 14:11:53 +0000
+++ init/job_process.c 2014-07-10 07:54:25 +0000
@@ -1474,6 +1474,11 @@
        job = job_process_find (pid, &process);
        if (! job)
                return;
+
+ /* Child setup process died, before finishing the setup.
+ */
+ if (job->process_data[process] && job->process_data[process]->valid)
+ return;

This seems to be what is causing the branch to fail to boot too.

1647. By Dimitri John Ledkov

Backout "fix" that causes boot regression.

This is meant to skip child process sigchild processing if
asynchronous setup notification pipe has not been closed/read-from
yet.

1648. By Dimitri John Ledkov

Merge trunk

1649. By Dimitri John Ledkov

Assert job_change_state is not blocked

1650. By Dimitri John Ledkov

Back out more of -r1647

1651. By Dimitri John Ledkov

Revert asserting no blockers, as we can get blockers.

1652. By Dimitri John Ledkov

Don't transition and return if blocked.... and don't assert before that check.

1653. By Dimitri John Ledkov

Merge

1654. By Dimitri John Ledkov

Derace real & mock signal handlers

1655. By Dimitri John Ledkov

Merge jodh tests

1656. By Dimitri John Ledkov

Make test_initctl pass without inotify support.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ChangeLog'
2--- ChangeLog 2014-07-08 14:11:53 +0000
3+++ ChangeLog 2014-07-11 12:53:11 +0000
4@@ -1,3 +1,18 @@
5+2014-07-09 James Hunt <james.hunt@ubuntu.com>
6+
7+ * init/job_process.c: Unhide job_process_error_abort() to allow it to be
8+ called by the tests.
9+ * init/tests/test_job_process.c: RESILIENT_TEST_CHILD(): New macro
10+ to work around a bug in NIH's TEST_CHILD() where it doesn't handle
11+ EINTR.
12+ * init/tests/test_job_process.c: test_handler(): New tests to ensure
13+ async handling can cope with both 'waitid() before select()' and
14+ vice versa:
15+ - "with child exit notification before child setup success notification"
16+ - "with child exit notification before child setup failure notification"
17+ - "with child setup success notification before child exit notification"
18+ - "with child setup failure notification before child exit notification"
19+
20 2014-07-08 James Hunt <james.hunt@ubuntu.com>
21
22 * init/main.c: main():
23
24=== modified file 'init/job.c'
25--- init/job.c 2014-06-12 14:23:47 +0000
26+++ init/job.c 2014-07-11 12:53:11 +0000
27@@ -396,11 +396,6 @@
28 {
29 nih_assert (job != NULL);
30
31- /* We may not be blocked by any events when doing first
32- * transition.
33- */
34- nih_assert (job->blocker == NULL);
35-
36 while (job->state != state) {
37 JobState old_state;
38 int unused;
39
40=== modified file 'init/job_process.c'
41--- init/job_process.c 2014-07-08 14:11:53 +0000
42+++ init/job_process.c 2014-07-11 12:53:11 +0000
43@@ -111,9 +111,6 @@
44 int disable_respawn = FALSE;
45
46 /* Prototypes for static functions */
47-static void job_process_error_abort (int fd, JobProcessErrorType type,
48- int arg)
49- __attribute__ ((noreturn));
50 static void job_process_remap_fd (int *fd, int reserved_fd, int error_fd);
51
52 /**
53@@ -983,7 +980,7 @@
54 *
55 * This function calls the exit() system call, so never returns.
56 **/
57-static void
58+void
59 job_process_error_abort (int fd,
60 JobProcessErrorType type,
61 int arg)
62@@ -2457,7 +2454,15 @@
63
64 err = nih_error_get ();
65
66- nih_assert (err->number == JOB_PROCESS_ERROR);
67+ if (err->number != JOB_PROCESS_ERROR) {
68+ nih_warn ("%s: %s", _("Temporary process spawn error"),
69+ err->message);
70+ nih_free (err);
71+ return;
72+ }
73+
74+ /* Wilco. Out. */
75+ nih_io_buffer_shrink (io->recv_buf, len);
76
77 /* Non-temporary error condition */
78 nih_warn (_("Failed to spawn %s %s process: %s"),
79@@ -2491,12 +2496,12 @@
80 /* Note that pts_master is closed automatically in the parent
81 * when the log object is destroyed.
82 */
83+ process_data->valid = FALSE;
84
85 nih_io_shutdown (io);
86
87 /* Invalidate */
88 process_data->job_process_fd = -1;
89- process_data->valid = FALSE;
90 }
91
92 /**
93@@ -2519,6 +2524,8 @@
94 */
95 if (! process_data)
96 return;
97+ if (! process_data->valid)
98+ return;
99
100 nih_assert (io);
101
102
103=== modified file 'init/job_process.h'
104--- init/job_process.h 2014-06-02 20:29:33 +0000
105+++ init/job_process.h 2014-07-11 12:53:11 +0000
106@@ -194,6 +194,10 @@
107
108 void job_process_error_handler (const char *buf, size_t len);
109
110+void job_process_error_abort (int fd, JobProcessErrorType type,
111+ int arg)
112+ __attribute__ ((noreturn));
113+
114 NIH_END_EXTERN
115
116 #endif /* INIT_JOB_PROCESS_H */
117
118=== modified file 'init/tests/test_job_process.c'
119--- init/tests/test_job_process.c 2014-07-07 10:15:25 +0000
120+++ init/tests/test_job_process.c 2014-07-11 12:53:11 +0000
121@@ -122,6 +122,80 @@
122 TEST_EQ (ok, TRUE); \
123 } while (0)
124
125+
126+/*
127+ * Register regular child handler.
128+ * Register another handler to be called after the primary
129+ * Upstart handler to allow the test to exit the main loop
130+ * quickly on success.
131+ * Process the event queue each time through the main loop
132+ */
133+
134+#define TEST_INSTALL_CHILD_HANDLERS() \
135+ NIH_MUST (nih_child_add_watch (NULL, \
136+ -1, \
137+ NIH_CHILD_ALL, \
138+ test_job_process_handler,\
139+ NULL)); \
140+ NIH_MUST (nih_child_add_watch (NULL, \
141+ -1, \
142+ NIH_CHILD_ALL, \
143+ job_process_handler, \
144+ NULL)); \
145+ NIH_MUST (nih_main_loop_add_func (NULL, (NihMainLoopCb)event_poll, \
146+ NULL))
147+
148+
149+#define TEST_CLEAR_CHILD_STATUS() \
150+ do { \
151+ TEST_EQ (waitid (P_ALL, 0, &siginfo, WEXITED | WNOWAIT), -1); \
152+ TEST_EQ (errno, ECHILD); \
153+ errno = 0; \
154+ child_exit_after = 1; \
155+ for (int _i = 0; _i < PROCESS_LAST; _i++) { \
156+ child_exit_status[_i] = -1; \
157+ } \
158+ } while (0)
159+
160+
161+/* Modified version of NIH's TEST_CHILD() that is resilient
162+ * to temporary errors.
163+ */
164+#define RESILIENT_TEST_CHILD(_pid) \
165+ do { \
166+ int _test_fds[2]; \
167+ fflush (stdout); \
168+ fflush (stderr); \
169+ assert0 (pipe (_test_fds)); \
170+ _pid = fork (); \
171+ if (_pid > 0) { \
172+ ssize_t ret; \
173+ char _test_buf[1]; \
174+ close (_test_fds[1]); \
175+ while (TRUE) { \
176+ ret = read (_test_fds[0], _test_buf, 1); \
177+ if (ret > 0) { \
178+ assert (ret == 1); \
179+ break; \
180+ } else if (ret < 0 && errno != EINTR) { \
181+ nih_assert_not_reached (); \
182+ } else { \
183+ nih_assert_not_reached (); \
184+ } \
185+ } \
186+ close (_test_fds[0]); \
187+ } else if (_pid == 0) { \
188+ close (_test_fds[0]); \
189+ assert (write (_test_fds[1], "\n", 1) == 1); \
190+ close (_test_fds[1]); \
191+ } \
192+ } while (0); \
193+ if (_pid == 0) \
194+ for (int _test_child = 0; _test_child < 2; _test_child++) \
195+ if (_test_child) { \
196+ abort (); \
197+ } else
198+
199 /* Sadly we can't test everything that job_process_spawn() does simply because
200 * a lot of it can only be done by root, or in the case of the console stuff,
201 * kills whatever had /dev/console (usually X).
202@@ -147,6 +221,36 @@
203 static int get_available_pty_count (void) __attribute__((unused));
204 static void close_all_files (void);
205
206+static int child_exit_status[PROCESS_LAST];
207+static int child_exit_after;
208+
209+/**
210+ * test_job_process_handler:
211+ *
212+ * @data: existing NihList that this function will add entries to,
213+ * @pid: process that changed,
214+ * @event: event that occurred on the child,
215+ * @status: exit status, signal raised or ptrace event.
216+ *
217+ * Handler that just sets some globals and requests the main loop to
218+ * exit to allow the test that installs it to check the values passed to
219+ * this function as appropriate.
220+ **/
221+void
222+test_job_process_handler (void *data,
223+ pid_t pid,
224+ NihChildEvents event,
225+ int status)
226+{
227+ if (event != NIH_CHILD_EXITED)
228+ return;
229+ child_exit_after--;
230+ child_exit_status[child_exit_after] = status;
231+ if (child_exit_after < 1)
232+ nih_main_loop_exit (0);
233+}
234+
235+
236 static void
237 child (enum child_tests test,
238 const char *filename)
239@@ -1056,6 +1160,7 @@
240 nih_free (class);
241 }
242
243+
244 /* Check that if we try and run a command that doesn't exist,
245 * job_process_start() raises a ProcessError and the command doesn't
246 * have any stored process id for it.
247@@ -1063,10 +1168,14 @@
248 TEST_FEATURE ("with no such file");
249 TEST_HASH_EMPTY (job_classes);
250
251+ TEST_RESET_MAIN_LOOP ();
252+ TEST_INSTALL_CHILD_HANDLERS ();
253+
254 output = tmpfile ();
255
256 TEST_ALLOC_FAIL {
257 TEST_ALLOC_SAFE {
258+ TEST_HASH_EMPTY (job_classes);
259 class = job_class_new (NULL, "test", NULL);
260 class->console = CONSOLE_NONE;
261 class->process[PROCESS_MAIN] = process_new (class);
262@@ -1076,12 +1185,16 @@
263 job = job_new (class, "foo");
264 job->goal = JOB_START;
265 job->state = JOB_SPAWNED;
266+
267+ nih_hash_add (job_classes, &class->entry);
268+ TEST_CLEAR_CHILD_STATUS ();
269 }
270
271 TEST_DIVERT_STDERR (output) {
272 job_process_start (job, PROCESS_MAIN);
273- TEST_WATCH_LOOP ();
274- event_poll ();
275+ TEST_GT (job->pid[PROCESS_MAIN], 0);
276+ TEST_EQ (nih_main_loop (), 0);
277+ TEST_EQ (child_exit_status[PROCESS_MAIN], 255);
278 }
279 rewind (output);
280
281@@ -1098,6 +1211,8 @@
282
283 TEST_EQ (rmdir (dirname), 0);
284
285+ TEST_RESET_MAIN_LOOP ();
286+
287 TEST_FILENAME (dirname);
288 TEST_EQ (mkdir (dirname, 0755), 0);
289
290@@ -3018,6 +3133,9 @@
291 TEST_FEATURE ("with single-line command running an invalid command");
292 TEST_HASH_EMPTY (job_classes);
293
294+ TEST_RESET_MAIN_LOOP ();
295+ TEST_INSTALL_CHILD_HANDLERS ();
296+
297 class = job_class_new (NULL, "buzz", NULL);
298 TEST_NE_P (class, NULL);
299
300@@ -3039,14 +3157,21 @@
301 job->goal = JOB_START;
302 job->state = JOB_SPAWNED;
303
304+ /* XXX: Manually add the class so job_process_find() works */
305+ nih_hash_add (job_classes, &class->entry);
306+
307 output = tmpfile ();
308 TEST_NE_P (output, NULL);
309+ TEST_CLEAR_CHILD_STATUS ();
310 TEST_DIVERT_STDERR (output) {
311 job_process_start (job, PROCESS_MAIN);
312- TEST_WATCH_UPDATE ();
313- TEST_WATCH_UPDATE ();
314- event_poll ();
315+ TEST_GT (job->pid[PROCESS_MAIN], 0);
316+ TEST_EQ (nih_main_loop (), 0);
317+ TEST_EQ (child_exit_status[PROCESS_MAIN], 255);
318 }
319+
320+ TEST_FILE_END (output);
321+
322 fclose (output);
323
324 /* We don't expect a logfile to be written since there is no
325@@ -3056,11 +3181,14 @@
326 TEST_EQ (errno, ENOENT);
327
328 nih_free (class);
329+ TEST_RESET_MAIN_LOOP ();
330
331 /************************************************************/
332 TEST_FEATURE ("with single-line command running an invalid command, then a 1-line post-stop script");
333 TEST_HASH_EMPTY (job_classes);
334
335+ TEST_INSTALL_CHILD_HANDLERS ();
336+
337 class = job_class_new (NULL, "asterix", NULL);
338 TEST_NE_P (class, NULL);
339
340@@ -3086,6 +3214,9 @@
341
342 job = job_new (class, "");
343
344+ /* XXX: Manually add the class so job_process_find() works */
345+ nih_hash_add (job_classes, &class->entry);
346+
347 output = tmpfile ();
348 TEST_NE_P (output, NULL);
349 TEST_DIVERT_STDERR (output) {
350@@ -3093,37 +3224,18 @@
351 job->goal = JOB_START;
352 job->state = JOB_SPAWNED;
353
354+ TEST_CLEAR_CHILD_STATUS ();
355+ child_exit_after = 2;
356 job_process_start (job, PROCESS_MAIN);
357- TEST_WATCH_UPDATE ();
358-
359- /* We don't expect a logfile to be written since there is no
360- * accompanying shell to write the error.
361- */
362- TEST_EQ (stat (filename, &statbuf), -1);
363- TEST_EQ (errno, ENOENT);
364-
365- job->goal = JOB_STOP;
366- job->state = JOB_POST_STOP;
367-
368- job_process_start (job, PROCESS_POST_STOP);
369-
370- TEST_NE (job->pid[PROCESS_POST_STOP], 0);
371- TEST_WATCH_UPDATE ();
372-
373- /* Flush the io so that the shell on the client side
374- * gets the data (the script to execute).
375- */
376- TEST_WATCH_UPDATE ();
377-
378- waitpid (job->pid[PROCESS_POST_STOP], &status, 0);
379- TEST_TRUE (WIFEXITED (status));
380- TEST_EQ (WEXITSTATUS (status), 0);
381-
382- TEST_WATCH_UPDATE ();
383-
384- /* .. but the post stop should have written data */
385+ TEST_GT (job->pid[PROCESS_MAIN], 0);
386+ TEST_EQ (nih_main_loop (), 0);
387+ /* Check exit status in reverse order */
388+ /* Main */
389+ TEST_EQ (child_exit_status[1], 255);
390+ /* Post-stop */
391+ TEST_EQ (child_exit_status[0], 0);
392+ /* And the post stop should have written data */
393 TEST_EQ (stat (filename, &statbuf), 0);
394- event_poll ();
395 }
396 fclose (output);
397
398@@ -3144,6 +3256,9 @@
399 TEST_FEATURE ("with single-line command running an invalid command, then a 2-line post-stop script");
400 TEST_HASH_EMPTY (job_classes);
401
402+ TEST_RESET_MAIN_LOOP ();
403+ TEST_INSTALL_CHILD_HANDLERS ();
404+
405 class = job_class_new (NULL, "asterix", NULL);
406 TEST_NE_P (class, NULL);
407
408@@ -3168,6 +3283,8 @@
409 TEST_EQ (errno, ENOENT);
410
411 job = job_new (class, "");
412+ /* XXX: Manually add the class so job_process_find() works */
413+ nih_hash_add (job_classes, &class->entry);
414
415 output = tmpfile ();
416 TEST_NE_P (output, NULL);
417@@ -3176,39 +3293,17 @@
418 job->goal = JOB_START;
419 job->state = JOB_SPAWNED;
420
421+ TEST_CLEAR_CHILD_STATUS ();
422+ child_exit_after = 2;
423 job_process_start (job, PROCESS_MAIN);
424- TEST_WATCH_UPDATE ();
425- TEST_WATCH_UPDATE ();
426-
427- /* We don't expect a logfile to be written since there is no
428- * accompanying shell to write the error.
429- */
430- TEST_EQ (stat (filename, &statbuf), -1);
431- TEST_EQ (errno, ENOENT);
432-
433- job->goal = JOB_STOP;
434- job->state = JOB_POST_STOP;
435-
436- job_process_start (job, PROCESS_POST_STOP);
437- TEST_WATCH_UPDATE ();
438-
439- TEST_NE (job->pid[PROCESS_POST_STOP], 0);
440-
441- /* Flush the io so that the shell on the client side
442- * gets the data (the script to execute).
443- */
444- TEST_WATCH_UPDATE ();
445-
446- waitpid (job->pid[PROCESS_POST_STOP], &status, 0);
447- TEST_TRUE (WIFEXITED (status));
448- TEST_EQ (WEXITSTATUS (status), 0);
449-
450- /* Allow the log to be written */
451- TEST_WATCH_UPDATE ();
452-
453- /* .. but the post stop should have written data */
454+ TEST_NE (job->pid[PROCESS_MAIN], 0);
455+
456+ TEST_EQ (nih_main_loop (), 0);
457+ TEST_EQ (child_exit_status[1], 255);
458+ TEST_EQ (child_exit_status[0], 0);
459+
460+ /* And the post stop should have written data */
461 TEST_EQ (stat (filename, &statbuf), 0);
462- event_poll ();
463 }
464 fclose (output);
465
466@@ -3225,6 +3320,7 @@
467 TEST_EQ (unlink (filename), 0);
468
469 nih_free (class);
470+ TEST_RESET_MAIN_LOOP ();
471
472 /************************************************************/
473 TEST_FEATURE ("with single-line command running an invalid command, then a post-stop command");
474@@ -3255,6 +3351,9 @@
475
476 job = job_new (class, "");
477
478+ TEST_RESET_MAIN_LOOP ();
479+ TEST_INSTALL_CHILD_HANDLERS ();
480+
481 output = tmpfile ();
482 TEST_NE_P (output, NULL);
483 TEST_DIVERT_STDERR (output) {
484@@ -3262,37 +3361,19 @@
485 job->goal = JOB_START;
486 job->state = JOB_SPAWNED;
487
488+ TEST_CLEAR_CHILD_STATUS ();
489+ child_exit_after = 2;
490+
491 job_process_start (job, PROCESS_MAIN);
492- TEST_WATCH_UPDATE ();
493-
494- /* We don't expect a logfile to be written since there is no
495- * accompanying shell to write the error.
496- */
497- TEST_EQ (stat (filename, &statbuf), -1);
498- TEST_EQ (errno, ENOENT);
499-
500- job->goal = JOB_STOP;
501- job->state = JOB_POST_STOP;
502-
503- job_process_start (job, PROCESS_POST_STOP);
504- TEST_WATCH_UPDATE ();
505-
506- TEST_NE (job->pid[PROCESS_POST_STOP], 0);
507-
508- /* Flush the io so that the shell on the client side
509- * gets the data (the script to execute).
510- */
511- TEST_WATCH_UPDATE ();
512-
513- waitpid (job->pid[PROCESS_POST_STOP], &status, 0);
514- TEST_TRUE (WIFEXITED (status));
515- TEST_EQ (WEXITSTATUS (status), 0);
516-
517- TEST_WATCH_UPDATE ();
518-
519- /* .. but the post stop should have written data */
520+ TEST_GT (job->pid[PROCESS_MAIN], 0);
521+ TEST_EQ (nih_main_loop (), 0);
522+ TEST_GT (job->pid[PROCESS_POST_STOP], 0);
523+ TEST_EQ (child_exit_status[1], 255);
524+ TEST_EQ (child_exit_status[0], 0);
525+
526+ /* The post stop should have written data */
527 TEST_EQ (stat (filename, &statbuf), 0);
528- event_poll ();
529+
530 }
531 fclose (output);
532
533@@ -3309,6 +3390,8 @@
534
535 nih_free (class);
536
537+ TEST_RESET_MAIN_LOOP ();
538+
539 /************************************************************/
540 TEST_FEATURE ("with single-line command running an invalid command, then an invalid post-stop command");
541 TEST_HASH_EMPTY (job_classes);
542@@ -3338,6 +3421,9 @@
543
544 job = job_new (class, "");
545
546+ TEST_RESET_MAIN_LOOP ();
547+ TEST_INSTALL_CHILD_HANDLERS ();
548+
549 output = tmpfile ();
550 TEST_NE_P (output, NULL);
551 TEST_DIVERT_STDERR (output) {
552@@ -3345,29 +3431,24 @@
553 job->goal = JOB_START;
554 job->state = JOB_SPAWNED;
555
556+ TEST_CLEAR_CHILD_STATUS ();
557+ child_exit_after = 2;
558+
559 job_process_start (job, PROCESS_MAIN);
560- TEST_WATCH_UPDATE ();
561-
562- /* We don't expect a logfile to be written since there is no
563- * accompanying shell to write the error.
564- */
565- TEST_EQ (stat (filename, &statbuf), -1);
566- TEST_EQ (errno, ENOENT);
567-
568- job->goal = JOB_STOP;
569- job->state = JOB_POST_STOP;
570-
571- job_process_start (job, PROCESS_POST_STOP);
572- TEST_WATCH_UPDATE ();
573+ TEST_GT (job->pid[PROCESS_MAIN], 0);
574+ TEST_EQ (nih_main_loop (), 0);
575+ TEST_EQ (child_exit_status[1], 255);
576+ TEST_EQ (child_exit_status[0], 255);
577
578 /* Again, no file expected */
579 TEST_EQ (stat (filename, &statbuf), -1);
580 TEST_EQ (errno, ENOENT);
581- event_poll ();
582 }
583 fclose (output);
584 nih_free (class);
585
586+ TEST_RESET_MAIN_LOOP ();
587+
588 /************************************************************/
589 TEST_FEATURE ("with single-line command running a valid command, then a 1-line invalid post-stop command");
590 TEST_HASH_EMPTY (job_classes);
591@@ -3397,6 +3478,9 @@
592
593 job = job_new (class, "");
594
595+ TEST_RESET_MAIN_LOOP ();
596+ TEST_INSTALL_CHILD_HANDLERS ();
597+
598 output = tmpfile ();
599 TEST_NE_P (output, NULL);
600 TEST_DIVERT_STDERR (output) {
601@@ -3404,29 +3488,26 @@
602 job->goal = JOB_START;
603 job->state = JOB_SPAWNED;
604
605+ TEST_CLEAR_CHILD_STATUS ();
606+
607 job_process_start (job, PROCESS_MAIN);
608-
609- TEST_NE (job->pid[PROCESS_MAIN], 0);
610-
611- waitpid (job->pid[PROCESS_MAIN], &status, 0);
612- TEST_TRUE (WIFEXITED (status));
613- TEST_EQ (WEXITSTATUS (status), 0);
614-
615- /* Flush the io so that the shell on the client side
616- * gets the data (the script to execute).
617- */
618- TEST_WATCH_UPDATE ();
619+ TEST_GT (job->pid[PROCESS_MAIN], 0);
620+ TEST_EQ (nih_main_loop (), 0);
621+ TEST_EQ (child_exit_status[0], 0);
622+ TEST_EQ (child_exit_status[1], -1);
623
624 /* Expect a log file */
625 TEST_EQ (stat (filename, &statbuf), 0);
626
627 job->goal = JOB_STOP;
628 job->state = JOB_POST_STOP;
629+
630+ TEST_CLEAR_CHILD_STATUS ();
631
632 job_process_start (job, PROCESS_POST_STOP);
633- TEST_WATCH_UPDATE ();
634-
635- TEST_EQ (job->pid[PROCESS_POST_STOP], 0);
636+ TEST_GT (job->pid[PROCESS_POST_STOP], 0);
637+ TEST_EQ (nih_main_loop (), 0);
638+ TEST_EQ (child_exit_status[0], 255);
639 }
640 fclose (output);
641
642@@ -3443,10 +3524,15 @@
643
644 nih_free (class);
645
646+ TEST_RESET_MAIN_LOOP ();
647+
648 /************************************************************/
649 TEST_FEATURE ("with multi-line script running an invalid command");
650 TEST_HASH_EMPTY (job_classes);
651
652+ TEST_RESET_MAIN_LOOP ();
653+ TEST_INSTALL_CHILD_HANDLERS ();
654+
655 class = job_class_new (NULL, "blah", NULL);
656 TEST_NE_P (class, NULL);
657
658@@ -3463,17 +3549,13 @@
659 job = job_new (class, "");
660 job->goal = JOB_START;
661 job->state = JOB_SPAWNED;
662+ nih_hash_add (job_classes, &class->entry);
663+ TEST_CLEAR_CHILD_STATUS ();
664
665 job_process_start (job, PROCESS_MAIN);
666- TEST_WATCH_UPDATE ();
667-
668- TEST_NE (job->pid[PROCESS_MAIN], 0);
669-
670- TEST_WATCH_UPDATE ();
671- waitpid (job->pid[PROCESS_MAIN], &status, 0);
672- TEST_TRUE (WIFEXITED (status));
673- TEST_NE (WEXITSTATUS (status), 0);
674- TEST_WATCH_UPDATE ();
675+ TEST_GT (job->pid[PROCESS_MAIN], 0);
676+ TEST_EQ (nih_main_loop (), 0);
677+ TEST_EQ (child_exit_status[0], 127);
678
679 TEST_EQ (stat (filename, &statbuf), 0);
680
681@@ -3502,6 +3584,7 @@
682
683 TEST_EQ (unlink (filename), 0);
684 nih_free (class);
685+ TEST_RESET_MAIN_LOOP ();
686
687 /************************************************************/
688 TEST_FEATURE ("with multi-line script that writes 1 line to stdout then 1 line to stderr");
689@@ -3977,6 +4060,9 @@
690 */
691 TEST_FEATURE ("with setuid");
692 TEST_HASH_EMPTY (job_classes);
693+ TEST_RESET_MAIN_LOOP ();
694+ TEST_INSTALL_CHILD_HANDLERS ();
695+
696
697 TEST_NE_P (output, NULL);
698 TEST_ALLOC_FAIL {
699@@ -3999,30 +4085,30 @@
700 job->goal = JOB_START;
701 job->state = JOB_SPAWNED;
702
703+ nih_hash_add (job_classes, &class->entry);
704+ TEST_CLEAR_CHILD_STATUS ();
705+
706 output = tmpfile ();
707 }
708
709 TEST_DIVERT_STDERR (output) {
710 job_process_start (job, PROCESS_MAIN);
711- TEST_WATCH_UPDATE ();
712+ TEST_GT (job->pid[PROCESS_MAIN], 0);
713+ TEST_EQ (nih_main_loop (), 0);
714 }
715
716 if (geteuid() == 0 || getuid() == pwd->pw_uid) {
717- TEST_NE (job->pid[PROCESS_MAIN], 0);
718-
719- waitpid (job->pid[PROCESS_MAIN], NULL, 0);
720 TEST_EQ (stat (filename, &statbuf), 0);
721- }
722- else {
723+ } else {
724 TEST_EQ (stat (filename, &statbuf), -1);
725- event_poll ();
726 }
727
728 unlink (filename);
729 nih_free (class);
730 }
731+
732+ TEST_RESET_MAIN_LOOP ();
733
734- /* FIXME with async spawn this test is racy */
735
736 /************************************************************/
737 TEST_FEATURE ("with multiple processes and log");
738@@ -4062,10 +4148,10 @@
739
740 job = job_new (class, "");
741 job->goal = JOB_START;
742- job->state = JOB_SPAWNED;
743+ job->state = JOB_SPAWNING;
744
745 job_process_start (job, PROCESS_MAIN);
746- while (stat (filename, &statbuf) != 0) {
747+ while (stat (filename, &statbuf) != 0 || statbuf.st_size < 9) {
748 TEST_WATCH_UPDATE ();
749 }
750 pid = job->pid[PROCESS_MAIN];
751@@ -4077,9 +4163,7 @@
752 TEST_NE_P (output, NULL);
753
754 /* initial output from main process */
755- CHECK_FILE_EQ (output, "started\r\n", TRUE);
756-
757- TEST_FILE_END (output);
758+ TEST_FILE_EQ (output, "started\r\n");
759
760 TEST_EQ (fclose (output), 0);
761
762@@ -4093,7 +4177,10 @@
763 waitpid (pid, &status, 0);
764 TEST_TRUE (WIFEXITED (status));
765 TEST_EQ (WEXITSTATUS (status), 0);
766- TEST_WATCH_UPDATE ();
767+
768+ while (stat (filename, &statbuf) != 0 || statbuf.st_size < 25) {
769+ TEST_WATCH_UPDATE ();
770+ }
771
772 output = fopen (filename, "r");
773 TEST_NE_P (output, NULL);
774@@ -5488,6 +5575,8 @@
775 char dirname[PATH_MAX];
776 nih_local char *logfile = NULL;
777 int fds[2] = { -1, -1};
778+ NihIo *io = NULL;
779+ nih_local NihIoBuffer *buffer= NULL;
780
781 TEST_FILENAME (dirname);
782 TEST_EQ (mkdir (dirname, 0755), 0);
783@@ -8770,13 +8859,288 @@
784
785 fclose (output);
786
787+ nih_free (event);
788+ event_poll ();
789+
790+ TEST_RESET_MAIN_LOOP ();
791+
792+ TEST_NE_P (class->process[PROCESS_MAIN], NULL);
793+ TEST_EQ_P (class->process[PROCESS_PRE_START], NULL);
794+ TEST_EQ_P (class->process[PROCESS_POST_START], NULL);
795+ TEST_EQ_P (class->process[PROCESS_PRE_STOP], NULL);
796+ TEST_EQ_P (class->process[PROCESS_POST_STOP], NULL);
797+ TEST_EQ_P (class->process[PROCESS_SECURITY], NULL);
798+
799+ /************************************************************/
800+ /* Ensure that if a child is setup successfully and then exits
801+ * before the main loop detects the child fd has closed (due to
802+ * the child calling execvp()), that the state is correct.
803+ */
804+ TEST_FEATURE ("with child exit notification before child setup success notification");
805+
806+ job = job_new (class, "");
807+ TEST_NE_P (job, NULL);
808+
809+ job->goal = JOB_START;
810+ job->state = JOB_SPAWNING;
811+
812+ assert0 (pipe (fds));
813+
814+ job->process_data[PROCESS_MAIN] = job_process_data_new (job->process_data,
815+ job, PROCESS_MAIN, fds[0]);
816+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
817+
818+ TEST_NE_P (class->process[PROCESS_MAIN], NULL);
819+ TEST_EQ_P (class->process[PROCESS_PRE_START], NULL);
820+ TEST_EQ_P (class->process[PROCESS_POST_START], NULL);
821+ TEST_EQ_P (class->process[PROCESS_PRE_STOP], NULL);
822+ TEST_EQ_P (class->process[PROCESS_POST_STOP], NULL);
823+ TEST_EQ_P (class->process[PROCESS_SECURITY], NULL);
824+
825+ /* used to check if job_process_terminated() called */
826+ job->process_data[PROCESS_MAIN]->status = -1;
827+
828+ TEST_CHILD (job->pid[PROCESS_MAIN]) {
829+ close (fds[0]);
830+
831+ nih_io_set_cloexec (fds[1]);
832+
833+ execl ("/bin/true", "/bin/true", NULL);
834+ }
835+ close (fds[1]);
836+
837+ TEST_FREE_TAG (job);
838+
839+ job_process_handler (NULL, job->pid[PROCESS_MAIN],
840+ NIH_CHILD_EXITED, 0);
841+
842+ TEST_NOT_FREE (job);
843+
844+ TEST_TRUE (job->process_data[PROCESS_MAIN]->valid);
845+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, fds[0]);
846+ TEST_EQ (job->process_data[PROCESS_MAIN]->shell_fd, -1);
847+ TEST_EQ_P (job->process_data[PROCESS_MAIN]->script, NULL);
848+
849+ /* job_process_terminated() should have been called now and the
850+ * status recorded.
851+ */
852+ TEST_EQ (job->process_data[PROCESS_MAIN]->status, 0);
853+
854+ /* goal should not change until the IO handlers have had a
855+ * chance to run.
856+ */
857+ TEST_EQ (job->goal, JOB_START);
858+ TEST_EQ (job->state, JOB_SPAWNED);
859+
860+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
861+
862+ close (fds[0]);
863+
864+ pid = job->pid[PROCESS_MAIN];
865+
866+ TEST_EQ (timed_waitpid (pid, 5), pid);
867+
868+ nih_free (job);
869+ TEST_RESET_MAIN_LOOP ();
870+
871+ /************************************************************/
872+ /* Ensure that if a child failed to be setup and then exits
873+ * before the main loop detects the child fd has data to read
874+ * that the state is correct.
875+ */
876+ TEST_FEATURE ("with child exit notification before child setup failure notification");
877+
878+ job = job_new (class, "");
879+ TEST_NE_P (job, NULL);
880+
881+ job->goal = JOB_START;
882+ job->state = JOB_SPAWNING;
883+
884+ assert0 (pipe (fds));
885+
886+ job->process_data[PROCESS_MAIN] = job_process_data_new (job->process_data,
887+ job, PROCESS_MAIN, fds[0]);
888+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
889+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, fds[0]);
890+ TEST_EQ (job->process_data[PROCESS_MAIN]->process, PROCESS_MAIN);
891+
892+ TEST_CHILD (job->pid[PROCESS_MAIN]) {
893+ close (fds[0]);
894+
895+ nih_error_raise_no_memory ();
896+ job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CGROUP_SETUP, 0);
897+ }
898+ close (fds[1]);
899+
900+ TEST_FREE_TAG (job);
901+
902+ job_process_handler (NULL, job->pid[PROCESS_MAIN],
903+ NIH_CHILD_DUMPED, 255);
904+
905+ TEST_NOT_FREE (job);
906+
907+ /* goal should not change until the IO handlers have had a
908+ * chance to run.
909+ */
910+ TEST_EQ (job->goal, JOB_START);
911+
912+ TEST_EQ (job->state, JOB_SPAWNED);
913+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
914+
915+ /* Still valid because the IO handlers haven't fired yet */
916+ TEST_TRUE (job->process_data[PROCESS_MAIN]->valid);
917+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, fds[0]);
918+
919+ TEST_EQ (job->process_data[PROCESS_MAIN]->shell_fd, -1);
920+ TEST_EQ_P (job->process_data[PROCESS_MAIN]->script, NULL);
921+
922+ /* job_process_terminated() will have been called now */
923+ status = job->process_data[PROCESS_MAIN]->status;
924+ TEST_GT (status, 0);
925+
926+ TEST_TRUE (WIFEXITED (status));
927+ TEST_EQ (WEXITSTATUS (status), 255);
928+
929+ /* slurp - don't care about content */
930+ buffer = read_from_fd (NULL, fds[0]);
931+ close (fds[0]);
932+
933+ pid = job->pid[PROCESS_MAIN];
934+ TEST_EQ (timed_waitpid (pid, 5), pid);
935+
936+ nih_free (job);
937+ TEST_RESET_MAIN_LOOP ();
938+
939+ /************************************************************/
940+ TEST_FEATURE ("with child setup success notification before child exit notification");
941+
942+ job = job_new (class, "");
943+ TEST_NE_P (job, NULL);
944+
945+ job->goal = JOB_START;
946+ job->state = JOB_SPAWNING;
947+
948+ assert0 (pipe (fds));
949+
950+ job->process_data[PROCESS_MAIN] = job_process_data_new (job->process_data,
951+ job, PROCESS_MAIN, fds[0]);
952+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
953+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, fds[0]);
954+ TEST_EQ (job->process_data[PROCESS_MAIN]->process, PROCESS_MAIN);
955+
956+ io = nih_io_reopen (job->process_data[PROCESS_MAIN],
957+ fds[0],
958+ NIH_IO_STREAM,
959+ (NihIoReader)job_process_child_reader,
960+ (NihIoCloseHandler)job_process_close_handler,
961+ NULL,
962+ job->process_data[PROCESS_MAIN]);
963+ TEST_NE_P (io, NULL);
964+
965+ TEST_CHILD (job->pid[PROCESS_MAIN]) {
966+ close (fds[0]);
967+
968+ nih_io_set_cloexec (fds[1]);
969+
970+ execl ("/bin/true", "/bin/true", NULL);
971+ }
972+ close (fds[1]);
973+
974+ job_process_close_handler (job->process_data[PROCESS_MAIN], io);
975+
976+ TEST_EQ (job->goal, JOB_START);
977+ TEST_EQ (job->state, JOB_SPAWNED);
978+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
979+
980+ /* Invalid because the IO handlers have now run */
981+ TEST_FALSE (job->process_data[PROCESS_MAIN]->valid);
982+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, -1);
983+
984+ TEST_EQ (job->process_data[PROCESS_MAIN]->shell_fd, -1);
985+ TEST_EQ_P (job->process_data[PROCESS_MAIN]->script, NULL);
986+ TEST_EQ (job->process_data[PROCESS_MAIN]->status, 0);
987+
988+ close (fds[0]);
989+
990+ pid = job->pid[PROCESS_MAIN];
991+ TEST_EQ (timed_waitpid (pid, 5), pid);
992+
993+ nih_free (job);
994+ TEST_RESET_MAIN_LOOP ();
995+
996+ /************************************************************/
997+ TEST_FEATURE ("with child setup failure notification before child exit notification");
998+
999+ job = job_new (class, "");
1000+ TEST_NE_P (job, NULL);
1001+
1002+ job->goal = JOB_START;
1003+ job->state = JOB_SPAWNED;
1004+
1005+ assert0 (pipe (fds));
1006+
1007+ job->process_data[PROCESS_MAIN] = job_process_data_new (job->process_data,
1008+ job, PROCESS_MAIN, fds[0]);
1009+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
1010+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, fds[0]);
1011+ TEST_EQ (job->process_data[PROCESS_MAIN]->process, PROCESS_MAIN);
1012+
1013+ /* Can't use job_register_child_handler() as we want the return
1014+ * value.
1015+ */
1016+ io = nih_io_reopen (job->process_data[PROCESS_MAIN],
1017+ fds[0],
1018+ NIH_IO_STREAM,
1019+ (NihIoReader)job_process_child_reader,
1020+ (NihIoCloseHandler)job_process_close_handler,
1021+ NULL,
1022+ job->process_data[PROCESS_MAIN]);
1023+ TEST_NE_P (io, NULL);
1024+
1025+ RESILIENT_TEST_CHILD (job->pid[PROCESS_MAIN]) {
1026+ close (fds[0]);
1027+ nih_error_raise_no_memory ();
1028+ job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CGROUP_SETUP, 0);
1029+ }
1030+ close (fds[1]);
1031+ pid = job->pid[PROCESS_MAIN];
1032+
1033+ buffer = read_from_fd (NULL, fds[0]);
1034+
1035+ job_process_child_reader (job->process_data[PROCESS_MAIN],
1036+ io, buffer->buf, buffer->len);
1037+
1038+ /* Setup failed, so goal should have changed to stop */
1039+ TEST_EQ (job->goal, JOB_STOP);
1040+ TEST_EQ (job->state, JOB_STOPPING);
1041+
1042+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
1043+
1044+ /* Invalid because the IO handlers have now run */
1045+ TEST_FALSE (job->process_data[PROCESS_MAIN]->valid);
1046+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, -1);
1047+
1048+ TEST_EQ (job->process_data[PROCESS_MAIN]->shell_fd, -1);
1049+ TEST_EQ_P (job->process_data[PROCESS_MAIN]->script, NULL);
1050+ TEST_EQ (job->process_data[PROCESS_MAIN]->shell_fd, -1);
1051+
1052+ /* Still zero because the process handler hasn't run yet */
1053+ TEST_EQ (job->process_data[PROCESS_MAIN]->status, 0);
1054+
1055+ close (fds[0]);
1056+
1057+ TEST_EQ (timed_waitpid (pid, 5), pid);
1058+
1059+ nih_free (job);
1060+
1061+ TEST_RESET_MAIN_LOOP ();
1062+
1063+ /************************************************************/
1064+
1065 nih_free (class);
1066 file->job = NULL;
1067 nih_free (source);
1068
1069- nih_free (event);
1070- event_poll ();
1071-
1072 TEST_EQ (rmdir (dirname), 0);
1073 TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0);
1074 }
1075
1076=== modified file 'test/test_util_common.c'
1077--- test/test_util_common.c 2014-06-02 23:32:49 +0000
1078+++ test/test_util_common.c 2014-07-11 12:53:11 +0000
1079@@ -375,6 +375,8 @@
1080 *
1081 * Simplified waitpid(2) with timeout using a pipe to allow select(2)
1082 * with timeout to be used to wait for process state change.
1083+ *
1084+ * Returns: as waitpid(2).
1085 **/
1086 pid_t
1087 timed_waitpid (pid_t pid, time_t timeout)
1088@@ -1000,7 +1002,7 @@
1089 nih_local char *cmd = NULL;
1090
1091 /* Clean up if tests forgot to */
1092- cmd = NIH_MUST (nih_sprintf (NULL, "rm %s/*.session 2>/dev/null", path));
1093+ cmd = NIH_MUST (nih_sprintf (NULL, "rm -f %s/*.session 2>/dev/null", path));
1094 assert0 (system (cmd));
1095
1096 /* Remove the directory tree the first Session Init created */
1097@@ -1094,10 +1096,13 @@
1098 buffer->buf + buffer->len,
1099 buffer->size - buffer->len);
1100
1101- if (len <= 0)
1102- break;
1103- else if (len > 0)
1104+ if (len < 0 && errno != EAGAIN && errno != EINTR) {
1105+ break;
1106+ } else if (! len) {
1107+ break;
1108+ } else if (len > 0) {
1109 buffer->len += len;
1110+ }
1111 }
1112
1113 close (fd);
1114
1115=== modified file 'util/tests/test_initctl.c'
1116--- util/tests/test_initctl.c 2014-07-01 15:34:42 +0000
1117+++ util/tests/test_initctl.c 2014-07-11 12:53:11 +0000
1118@@ -10968,9 +10968,9 @@
1119 /*******************************************************************/
1120 TEST_FEATURE ("single job");
1121
1122- START_UPSTART (upstart_pid, FALSE);
1123 CREATE_FILE (dirname, "foo.conf",
1124 "exec echo hello");
1125+ START_UPSTART (upstart_pid, FALSE);
1126
1127 cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
1128 TEST_NE_P (cmd, NULL);
1129@@ -10984,10 +10984,10 @@
1130 /*******************************************************************/
1131 TEST_FEATURE ("3 jobs and re-exec");
1132
1133- START_UPSTART (upstart_pid, FALSE);
1134- CREATE_FILE (dirname, "foo.conf", "exec echo foo");
1135+ CREATE_FILE (dirname, "foo.conf", "exec echo foo");
1136 CREATE_FILE (dirname, "bar.conf", "exec echo bar");
1137 CREATE_FILE (dirname, "baz.conf", "exec echo bar");
1138+ START_UPSTART (upstart_pid, FALSE);
1139
1140 cmd = nih_sprintf (NULL, "%s list 2>&1", get_initctl ());
1141 TEST_NE_P (cmd, NULL);
1142@@ -11110,6 +11110,12 @@
1143
1144 CREATE_FILE (confdir, "foo.conf", contents);
1145
1146+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1147+ TEST_NE_P (cmd, NULL);
1148+ RUN_COMMAND (NULL, cmd, &output, &lines);
1149+ TEST_EQ (lines, 0);
1150+ nih_free (output);
1151+
1152 cmd = nih_sprintf (NULL, "%s start foo 2>&1", get_initctl ());
1153 TEST_NE_P (cmd, NULL);
1154 RUN_COMMAND (NULL, cmd, &output, &lines);
1155@@ -12482,6 +12488,12 @@
1156 "author \"foo\"\n"
1157 "description \"wibble\"");
1158
1159+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1160+ TEST_NE_P (cmd, NULL);
1161+ RUN_COMMAND (NULL, cmd, &output, &lines);
1162+ TEST_EQ (lines, 0);
1163+ nih_free (output);
1164+
1165 cmd = nih_sprintf (NULL, "%s show-config foo 2>&1", get_initctl ());
1166 TEST_NE_P (cmd, NULL);
1167 RUN_COMMAND (NULL, cmd, &output, &lines);
1168@@ -12507,6 +12519,12 @@
1169 "emits \"thing\"\n"
1170 "description \"wibble\"");
1171
1172+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1173+ TEST_NE_P (cmd, NULL);
1174+ RUN_COMMAND (NULL, cmd, &output, &lines);
1175+ TEST_EQ (lines, 0);
1176+ nih_free (output);
1177+
1178 cmd = nih_sprintf (NULL, "%s show-config foo 2>&1", get_initctl ());
1179 TEST_NE_P (cmd, NULL);
1180 RUN_COMMAND (NULL, cmd, &output, &lines);
1181@@ -12535,6 +12553,12 @@
1182 "emits \"thong\"\n"
1183 "description \"wibble\"");
1184
1185+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1186+ TEST_NE_P (cmd, NULL);
1187+ RUN_COMMAND (NULL, cmd, &output, &lines);
1188+ TEST_EQ (lines, 0);
1189+ nih_free (output);
1190+
1191 cmd = nih_sprintf (NULL, "%s show-config foo 2>&1", get_initctl ());
1192 TEST_NE_P (cmd, NULL);
1193 RUN_COMMAND (NULL, cmd, &output, &lines);
1194@@ -12564,6 +12588,12 @@
1195 "start on (A and B)\n"
1196 "description \"wibble\"");
1197
1198+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1199+ TEST_NE_P (cmd, NULL);
1200+ RUN_COMMAND (NULL, cmd, &output, &lines);
1201+ TEST_EQ (lines, 0);
1202+ nih_free (output);
1203+
1204 cmd = nih_sprintf (NULL, "%s show-config foo 2>&1", get_initctl ());
1205 TEST_NE_P (cmd, NULL);
1206 RUN_COMMAND (NULL, cmd, &output, &lines);
1207@@ -12593,6 +12623,12 @@
1208 "start on (A and B)\n"
1209 "description \"wibble\"");
1210
1211+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1212+ TEST_NE_P (cmd, NULL);
1213+ RUN_COMMAND (NULL, cmd, &output, &lines);
1214+ TEST_EQ (lines, 0);
1215+ nih_free (output);
1216+
1217 cmd = nih_sprintf (NULL, "%s show-config foo 2>&1", get_initctl ());
1218 TEST_NE_P (cmd, NULL);
1219 RUN_COMMAND (NULL, cmd, &output, &lines);
1220@@ -12625,6 +12661,12 @@
1221 "emits \"stime\"\n"
1222 "description \"wibble\"");
1223
1224+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1225+ TEST_NE_P (cmd, NULL);
1226+ RUN_COMMAND (NULL, cmd, &output, &lines);
1227+ TEST_EQ (lines, 0);
1228+ nih_free (output);
1229+
1230 cmd = nih_sprintf (NULL, "%s show-config foo 2>&1", get_initctl ());
1231 TEST_NE_P (cmd, NULL);
1232 RUN_COMMAND (NULL, cmd, &output, &lines);
1233@@ -12657,6 +12699,12 @@
1234 "stop on (A or B)\n"
1235 "description \"wibble\"");
1236
1237+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1238+ TEST_NE_P (cmd, NULL);
1239+ RUN_COMMAND (NULL, cmd, &output, &lines);
1240+ TEST_EQ (lines, 0);
1241+ nih_free (output);
1242+
1243 cmd = nih_sprintf (NULL, "%s show-config foo 2>&1", get_initctl ());
1244 TEST_NE_P (cmd, NULL);
1245 RUN_COMMAND (NULL, cmd, &output, &lines);
1246@@ -12686,6 +12734,12 @@
1247 "stop on (A or B)\n"
1248 "description \"wibble\"");
1249
1250+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1251+ TEST_NE_P (cmd, NULL);
1252+ RUN_COMMAND (NULL, cmd, &output, &lines);
1253+ TEST_EQ (lines, 0);
1254+ nih_free (output);
1255+
1256 cmd = nih_sprintf (NULL, "%s show-config foo 2>&1", get_initctl ());
1257 TEST_NE_P (cmd, NULL);
1258 RUN_COMMAND (NULL, cmd, &output, &lines);
1259@@ -12718,6 +12772,12 @@
1260 "emits \"stime\"\n"
1261 "description \"wibble\"");
1262
1263+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1264+ TEST_NE_P (cmd, NULL);
1265+ RUN_COMMAND (NULL, cmd, &output, &lines);
1266+ TEST_EQ (lines, 0);
1267+ nih_free (output);
1268+
1269 cmd = nih_sprintf (NULL, "%s show-config foo 2>&1", get_initctl ());
1270 TEST_NE_P (cmd, NULL);
1271 RUN_COMMAND (NULL, cmd, &output, &lines);
1272@@ -12753,6 +12813,12 @@
1273 "start on (starting JOB=\"boo\" or B x=y)\n"
1274 "description \"wibble\"");
1275
1276+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1277+ TEST_NE_P (cmd, NULL);
1278+ RUN_COMMAND (NULL, cmd, &output, &lines);
1279+ TEST_EQ (lines, 0);
1280+ nih_free (output);
1281+
1282 cmd = nih_sprintf (NULL, "%s show-config foo 2>&1", get_initctl ());
1283 TEST_NE_P (cmd, NULL);
1284 RUN_COMMAND (NULL, cmd, &output, &lines);
1285@@ -12791,6 +12857,12 @@
1286 "start on (starting JOB=\"boo\" P=Q c=sea or B x=y)\n"
1287 "description \"wibble\"");
1288
1289+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1290+ TEST_NE_P (cmd, NULL);
1291+ RUN_COMMAND (NULL, cmd, &output, &lines);
1292+ TEST_EQ (lines, 0);
1293+ nih_free (output);
1294+
1295 cmd = nih_sprintf (NULL, "%s show-config foo 2>&1", get_initctl ());
1296 TEST_NE_P (cmd, NULL);
1297 RUN_COMMAND (NULL, cmd, &output, &lines);
1298@@ -12830,6 +12902,12 @@
1299 "start on A and (B FOO=BAR or starting C x=y)\n"
1300 "description \"wibble\"");
1301
1302+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1303+ TEST_NE_P (cmd, NULL);
1304+ RUN_COMMAND (NULL, cmd, &output, &lines);
1305+ TEST_EQ (lines, 0);
1306+ nih_free (output);
1307+
1308 cmd = nih_sprintf (NULL, "%s show-config foo 2>&1", get_initctl ());
1309 TEST_NE_P (cmd, NULL);
1310 RUN_COMMAND (NULL, cmd, &output, &lines);
1311@@ -12876,6 +12954,12 @@
1312 "(stopped gdm or stopped kdm or stopped xdm A=B or stopping lxdm)))\n"
1313 "description \"wibble\"");
1314
1315+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1316+ TEST_NE_P (cmd, NULL);
1317+ RUN_COMMAND (NULL, cmd, &output, &lines);
1318+ TEST_EQ (lines, 0);
1319+ nih_free (output);
1320+
1321 cmd = nih_sprintf (NULL, "%s show-config foo 2>&1", get_initctl ());
1322 TEST_NE_P (cmd, NULL);
1323 RUN_COMMAND (NULL, cmd, &output, &lines);
1324@@ -13011,6 +13095,12 @@
1325 "task\n"
1326 "exec true");
1327
1328+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1329+ TEST_NE_P (cmd, NULL);
1330+ RUN_COMMAND (NULL, cmd, &output, &lines);
1331+ TEST_EQ (lines, 0);
1332+ nih_free (output);
1333+
1334 cmd = nih_sprintf (NULL, "%s check-config 2>&1", get_initctl ());
1335 TEST_NE_P (cmd, NULL);
1336 RUN_COMMAND (NULL, cmd, &output, &lines);
1337@@ -13031,6 +13121,12 @@
1338 CREATE_FILE (dirname, "baz.conf",
1339 "emits wibble");
1340
1341+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1342+ TEST_NE_P (cmd, NULL);
1343+ RUN_COMMAND (NULL, cmd, &output, &lines);
1344+ TEST_EQ (lines, 0);
1345+ nih_free (output);
1346+
1347 cmd = nih_sprintf (NULL, "%s check-config 2>&1", get_initctl ());
1348 TEST_NE_P (cmd, NULL);
1349 RUN_COMMAND (NULL, cmd, &output, &lines);
1350@@ -13052,6 +13148,12 @@
1351 "task\n"
1352 "exec true");
1353
1354+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1355+ TEST_NE_P (cmd, NULL);
1356+ RUN_COMMAND (NULL, cmd, &output, &lines);
1357+ TEST_EQ (lines, 0);
1358+ nih_free (output);
1359+
1360 cmd = nih_sprintf (NULL, "%s check-config --ignore-events=wibble 2>&1",
1361 get_initctl ());
1362 TEST_NE_P (cmd, NULL);
1363@@ -13067,6 +13169,12 @@
1364 CREATE_FILE (dirname, "foo.conf",
1365 "start on (fred and wilma)");
1366
1367+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1368+ TEST_NE_P (cmd, NULL);
1369+ RUN_COMMAND (NULL, cmd, &output, &lines);
1370+ TEST_EQ (lines, 0);
1371+ nih_free (output);
1372+
1373 cmd = nih_sprintf (NULL, "%s check-config --ignore-events=wilma,foo,fred 2>&1",
1374 get_initctl ());
1375 TEST_NE_P (cmd, NULL);
1376@@ -13091,6 +13199,12 @@
1377 CREATE_FILE (dirname, "mountall.conf", "exec true");
1378 CREATE_FILE (dirname, "gdm.conf" , "exec true");
1379
1380+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1381+ TEST_NE_P (cmd, NULL);
1382+ RUN_COMMAND (NULL, cmd, &output, &lines);
1383+ TEST_EQ (lines, 0);
1384+ nih_free (output);
1385+
1386 cmd = nih_sprintf (NULL, "%s check-config --ignore-events=runlevel 2>&1",
1387 get_initctl ());
1388 TEST_NE_P (cmd, NULL);
1389@@ -13115,6 +13229,12 @@
1390
1391 CREATE_FILE (dirname, "mountall.conf", "exec true");
1392
1393+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1394+ TEST_NE_P (cmd, NULL);
1395+ RUN_COMMAND (NULL, cmd, &output, &lines);
1396+ TEST_EQ (lines, 0);
1397+ nih_free (output);
1398+
1399 cmd = nih_sprintf (NULL, "%s check-config --ignore-events=runlevel 2>&1",
1400 get_initctl ());
1401 TEST_NE_P (cmd, NULL);
1402@@ -13146,6 +13266,12 @@
1403 CREATE_FILE (dirname, "mountall.conf", "exec true");
1404 CREATE_FILE (dirname, "gdm.conf" , "exec true");
1405
1406+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1407+ TEST_NE_P (cmd, NULL);
1408+ RUN_COMMAND (NULL, cmd, &output, &lines);
1409+ TEST_EQ (lines, 0);
1410+ nih_free (output);
1411+
1412 cmd = nih_sprintf (NULL, "%s check-config --ignore-events=runlevel 2>&1",
1413 get_initctl ());
1414 TEST_NE_P (cmd, NULL);
1415@@ -13170,6 +13296,12 @@
1416
1417 CREATE_FILE (dirname, "mountall.conf", "exec true");
1418
1419+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1420+ TEST_NE_P (cmd, NULL);
1421+ RUN_COMMAND (NULL, cmd, &output, &lines);
1422+ TEST_EQ (lines, 0);
1423+ nih_free (output);
1424+
1425 cmd = nih_sprintf (NULL, "%s check-config --ignore-events=runlevel 2>&1",
1426 get_initctl ());
1427 TEST_NE_P (cmd, NULL);
1428@@ -13203,6 +13335,12 @@
1429 CREATE_FILE (dirname, "portmap.conf", "exec true");
1430 CREATE_FILE (dirname, "beano.conf", "exec true");
1431
1432+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1433+ TEST_NE_P (cmd, NULL);
1434+ RUN_COMMAND (NULL, cmd, &output, &lines);
1435+ TEST_EQ (lines, 0);
1436+ nih_free (output);
1437+
1438 cmd = nih_sprintf (NULL, "%s check-config --ignore-events=runlevel 2>&1",
1439 get_initctl ());
1440 TEST_NE_P (cmd, NULL);
1441@@ -13240,6 +13378,12 @@
1442 "emits hello");
1443 CREATE_FILE (dirname, "gdm.conf", "exec true");
1444
1445+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1446+ TEST_NE_P (cmd, NULL);
1447+ RUN_COMMAND (NULL, cmd, &output, &lines);
1448+ TEST_EQ (lines, 0);
1449+ nih_free (output);
1450+
1451 cmd = nih_sprintf (NULL, "%s check-config >&1",
1452 get_initctl ());
1453 TEST_NE_P (cmd, NULL);
1454@@ -13272,6 +13416,12 @@
1455 CREATE_FILE (dirname, "mountall.conf", "exec true");
1456 CREATE_FILE (dirname, "portmap.conf", "exec true");
1457
1458+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1459+ TEST_NE_P (cmd, NULL);
1460+ RUN_COMMAND (NULL, cmd, &output, &lines);
1461+ TEST_EQ (lines, 0);
1462+ nih_free (output);
1463+
1464 cmd = nih_sprintf (NULL, "%s check-config 2>&1",
1465 get_initctl ());
1466 TEST_NE_P (cmd, NULL);
1467@@ -13313,6 +13463,12 @@
1468 CREATE_FILE (dirname, "wibble.conf", "emits wibble");
1469 CREATE_FILE (dirname, "beano.conf", "exec true");
1470
1471+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1472+ TEST_NE_P (cmd, NULL);
1473+ RUN_COMMAND (NULL, cmd, &output, &lines);
1474+ TEST_EQ (lines, 0);
1475+ nih_free (output);
1476+
1477 cmd = nih_sprintf (NULL, "%s check-config 2>&1",
1478 get_initctl ());
1479 TEST_NE_P (cmd, NULL);
1480@@ -13350,6 +13506,12 @@
1481 CREATE_FILE (dirname, "wibble.conf", "emits wibble");
1482 CREATE_FILE (dirname, "beano.conf", "exec true");
1483
1484+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1485+ TEST_NE_P (cmd, NULL);
1486+ RUN_COMMAND (NULL, cmd, &output, &lines);
1487+ TEST_EQ (lines, 0);
1488+ nih_free (output);
1489+
1490 cmd = nih_sprintf (NULL, "%s check-config --warn 2>&1",
1491 get_initctl ());
1492 TEST_NE_P (cmd, NULL);
1493@@ -16080,6 +16242,12 @@
1494 "author \"foo\"\n"
1495 "description \"wibble\"");
1496
1497+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1498+ TEST_NE_P (cmd, NULL);
1499+ RUN_COMMAND (NULL, cmd, &output, &lines);
1500+ TEST_EQ (lines, 0);
1501+ nih_free (output);
1502+
1503 cmd = nih_sprintf (NULL, "%s usage foo 2>&1", get_initctl ());
1504 TEST_NE_P (cmd, NULL);
1505 RUN_COMMAND (NULL, cmd, &output, &lines);
1506@@ -16096,6 +16264,12 @@
1507 CREATE_FILE (dirname, "foo.conf",
1508 "usage \"this is usage\"");
1509
1510+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1511+ TEST_NE_P (cmd, NULL);
1512+ RUN_COMMAND (NULL, cmd, &output, &lines);
1513+ TEST_EQ (lines, 0);
1514+ nih_free (output);
1515+
1516 cmd = nih_sprintf (NULL, "%s usage foo 2>&1", get_initctl ());
1517 TEST_NE_P (cmd, NULL);
1518 RUN_COMMAND (NULL, cmd, &output, &lines);
1519@@ -16113,6 +16287,12 @@
1520 "instance $FOO\n"
1521 "usage \"this is usage\"");
1522
1523+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1524+ TEST_NE_P (cmd, NULL);
1525+ RUN_COMMAND (NULL, cmd, &output, &lines);
1526+ TEST_EQ (lines, 0);
1527+ nih_free (output);
1528+
1529 memset (&command, 0, sizeof command);
1530 args[0] = "foo";
1531 args[1] = NULL;
1532@@ -16246,6 +16426,12 @@
1533
1534 CREATE_FILE (confdir, "foo.conf", "exec env");
1535
1536+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1537+ TEST_NE_P (cmd, NULL);
1538+ RUN_COMMAND (NULL, cmd, &output, &line_count);
1539+ TEST_EQ (line_count, 0);
1540+ nih_free (output);
1541+
1542 cmd = nih_sprintf (NULL, "%s start foo 2>&1", get_initctl ());
1543 TEST_NE_P (cmd, NULL);
1544 RUN_COMMAND (NULL, cmd, &output, &line_count);
1545@@ -16393,6 +16579,12 @@
1546
1547 CREATE_FILE (confdir, "empty-env.conf", contents);
1548
1549+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1550+ TEST_NE_P (cmd, NULL);
1551+ RUN_COMMAND (NULL, cmd, &output, &line_count);
1552+ TEST_EQ (line_count, 0);
1553+ nih_free (output);
1554+
1555 cmd = nih_sprintf (NULL, "%s start empty-env 2>&1", get_initctl ());
1556 TEST_NE_P (cmd, NULL);
1557 RUN_COMMAND (NULL, cmd, &output, &line_count);
1558@@ -17504,6 +17696,12 @@
1559
1560 CREATE_FILE (confdir, "modified-env.conf", "exec env");
1561
1562+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1563+ TEST_NE_P (cmd, NULL);
1564+ RUN_COMMAND (NULL, cmd, &output, &line_count);
1565+ TEST_EQ (line_count, 0);
1566+ nih_free (output);
1567+
1568 cmd = nih_sprintf (NULL, "%s start modified-env 2>&1", get_initctl ());
1569 TEST_NE_P (cmd, NULL);
1570 RUN_COMMAND (NULL, cmd, &output, &line_count);
1571@@ -17629,6 +17827,12 @@
1572
1573 CREATE_FILE (confdir, "foo.conf", contents);
1574
1575+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1576+ TEST_NE_P (cmd, NULL);
1577+ RUN_COMMAND (NULL, cmd, &output, &line_count);
1578+ TEST_EQ (line_count, 0);
1579+ nih_free (output);
1580+
1581 cmd = nih_sprintf (NULL, "%s start foo 2>&1", get_initctl ());
1582 TEST_NE_P (cmd, NULL);
1583
1584@@ -17674,6 +17878,12 @@
1585
1586 CREATE_FILE (confdir, "foo.conf", contents);
1587
1588+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1589+ TEST_NE_P (cmd, NULL);
1590+ RUN_COMMAND (NULL, cmd, &output, &line_count);
1591+ TEST_EQ (line_count, 0);
1592+ nih_free (output);
1593+
1594 cmd = nih_sprintf (NULL, "%s start foo 2>&1", get_initctl ());
1595 TEST_NE_P (cmd, NULL);
1596 RUN_COMMAND (NULL, cmd, &output, &line_count);
1597@@ -17705,6 +17915,12 @@
1598
1599 CREATE_FILE (confdir, "bar.conf", contents);
1600
1601+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1602+ TEST_NE_P (cmd, NULL);
1603+ RUN_COMMAND (NULL, cmd, &output, &line_count);
1604+ TEST_EQ (line_count, 0);
1605+ nih_free (output);
1606+
1607 cmd = nih_sprintf (NULL, "%s start bar 2>&1", get_initctl ());
1608 TEST_NE_P (cmd, NULL);
1609 RUN_COMMAND (NULL, cmd, &output, &line_count);
1610@@ -17788,6 +18004,12 @@
1611
1612 CREATE_FILE (confdir, "foo.conf", "exec env");
1613
1614+ cmd = nih_sprintf (NULL, "%s reload-configuration 2>&1", get_initctl ());
1615+ TEST_NE_P (cmd, NULL);
1616+ RUN_COMMAND (NULL, cmd, &output, &lines);
1617+ TEST_EQ (lines, 0);
1618+ nih_free (output);
1619+
1620 cmd = nih_sprintf (NULL, "%s start foo 2>&1", get_initctl ());
1621 TEST_NE_P (cmd, NULL);
1622 RUN_COMMAND (NULL, cmd, &output, &lines);

Subscribers

People subscribed via source and target branches