Merge lp:~jamesodhunt/upstart/add-race-checking-tests into lp:upstart

Proposed by Dimitri John Ledkov on 2014-07-08
Status: Rejected
Rejected by: James Hunt on 2014-07-14
Proposed branch: lp:~jamesodhunt/upstart/add-race-checking-tests
Merge into: lp:upstart
Diff against target: 341 lines (+270/-7)
3 files modified
init/job_process.c (+1/-4)
init/job_process.h (+4/-0)
init/tests/test_job_process.c (+265/-3)
To merge this branch: bzr merge lp:~jamesodhunt/upstart/add-race-checking-tests
Reviewer Review Type Date Requested Status
Upstart Reviewers 2014-07-08 Pending
Review via email: mp+225963@code.launchpad.net
To post a comment you must log in.
1643. By James Hunt on 2014-07-08

* Sync with lp:upstart.

1644. By James Hunt on 2014-07-08

latest

James Hunt (jamesodhunt) wrote :

Unmerged revisions

1644. By James Hunt on 2014-07-08

latest

1643. By James Hunt on 2014-07-08

* Sync with lp:upstart.

1642. By James Hunt on 2014-07-03

* latest.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'init/job_process.c'
2--- init/job_process.c 2014-07-03 08:59:30 +0000
3+++ init/job_process.c 2014-07-08 17:02:18 +0000
4@@ -111,9 +111,6 @@
5 int disable_respawn = FALSE;
6
7 /* Prototypes for static functions */
8-static void job_process_error_abort (int fd, JobProcessErrorType type,
9- int arg)
10- __attribute__ ((noreturn));
11 static void job_process_remap_fd (int *fd, int reserved_fd, int error_fd);
12
13 /**
14@@ -983,7 +980,7 @@
15 *
16 * This function calls the exit() system call, so never returns.
17 **/
18-static void
19+void
20 job_process_error_abort (int fd,
21 JobProcessErrorType type,
22 int arg)
23
24=== modified file 'init/job_process.h'
25--- init/job_process.h 2014-06-02 20:29:33 +0000
26+++ init/job_process.h 2014-07-08 17:02:18 +0000
27@@ -194,6 +194,10 @@
28
29 void job_process_error_handler (const char *buf, size_t len);
30
31+void job_process_error_abort (int fd, JobProcessErrorType type,
32+ int arg)
33+ __attribute__ ((noreturn));
34+
35 NIH_END_EXTERN
36
37 #endif /* INIT_JOB_PROCESS_H */
38
39=== modified file 'init/tests/test_job_process.c'
40--- init/tests/test_job_process.c 2014-07-07 10:15:25 +0000
41+++ init/tests/test_job_process.c 2014-07-08 17:02:18 +0000
42@@ -5488,6 +5488,8 @@
43 char dirname[PATH_MAX];
44 nih_local char *logfile = NULL;
45 int fds[2] = { -1, -1};
46+ NihIo *io = NULL;
47+ nih_local NihIoBuffer *buffer= NULL;
48
49 TEST_FILENAME (dirname);
50 TEST_EQ (mkdir (dirname, 0755), 0);
51@@ -8770,13 +8772,269 @@
52
53 fclose (output);
54
55+ nih_free (event);
56+ event_poll ();
57+
58+ TEST_RESET_MAIN_LOOP ();
59+
60+ TEST_NE_P (class->process[PROCESS_MAIN], NULL);
61+ TEST_EQ_P (class->process[PROCESS_PRE_START], NULL);
62+ TEST_EQ_P (class->process[PROCESS_POST_START], NULL);
63+ TEST_EQ_P (class->process[PROCESS_PRE_STOP], NULL);
64+ TEST_EQ_P (class->process[PROCESS_POST_STOP], NULL);
65+ TEST_EQ_P (class->process[PROCESS_SECURITY], NULL);
66+
67+ /* FIXME */
68+#if 0
69+ /************************************************************/
70+ /* Ensure that if a child is setup successfully and then exits
71+ * before the main loop detects the child fd has closed (due to
72+ * the child calling execvp()), that the state is correct.
73+ */
74+ TEST_FEATURE ("with child exit notification before child setup success notification");
75+
76+ job = job_new (class, "");
77+ TEST_NE_P (job, NULL);
78+
79+ job->goal = JOB_START;
80+ job->state = JOB_SPAWNING;
81+
82+ assert0 (pipe (fds));
83+
84+ job->process_data[PROCESS_MAIN] = job_process_data_new (job->process_data,
85+ job, PROCESS_MAIN, fds[0]);
86+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
87+
88+ TEST_NE_P (class->process[PROCESS_MAIN], NULL);
89+ TEST_EQ_P (class->process[PROCESS_PRE_START], NULL);
90+ TEST_EQ_P (class->process[PROCESS_POST_START], NULL);
91+ TEST_EQ_P (class->process[PROCESS_PRE_STOP], NULL);
92+ TEST_EQ_P (class->process[PROCESS_POST_STOP], NULL);
93+ TEST_EQ_P (class->process[PROCESS_SECURITY], NULL);
94+
95+ TEST_CHILD (job->pid[PROCESS_MAIN]) {
96+ close (fds[0]);
97+
98+ nih_io_set_cloexec (fds[1]);
99+
100+ execl ("/bin/true", "/bin/true", NULL);
101+ }
102+ close (fds[1]);
103+
104+ TEST_FREE_TAG (job);
105+
106+ job_process_handler (NULL, job->pid[PROCESS_MAIN],
107+ NIH_CHILD_EXITED, 0);
108+
109+ TEST_NOT_FREE (job);
110+
111+ /* goal should not change until the IO handlers have had a
112+ * chance to run.
113+ */
114+ TEST_EQ (job->goal, JOB_START);
115+
116+ TEST_EQ (job->state, JOB_SPAWNED);
117+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
118+
119+ TEST_TRUE (job->process_data[PROCESS_MAIN]->valid);
120+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, fds[0]);
121+ TEST_EQ (job->process_data[PROCESS_MAIN]->shell_fd, -1);
122+ TEST_EQ_P (job->process_data[PROCESS_MAIN]->script, NULL);
123+ TEST_EQ (job->process_data[PROCESS_MAIN]->status, 0);
124+
125+ close (fds[0]);
126+ nih_free (job);
127+
128+ TEST_RESET_MAIN_LOOP ();
129+
130+ /************************************************************/
131+ /* Ensure that if a child failed to be setup and then exits
132+ * before the main loop detects the child fd has data to read
133+ * that the state is correct.
134+ */
135+ TEST_FEATURE ("with child exit notification before child setup failure notification");
136+
137+ job = job_new (class, "");
138+ TEST_NE_P (job, NULL);
139+
140+ job->goal = JOB_START;
141+ job->state = JOB_SPAWNING;
142+
143+ assert0 (pipe (fds));
144+
145+ job->process_data[PROCESS_MAIN] = job_process_data_new (job->process_data,
146+ job, PROCESS_MAIN, fds[0]);
147+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
148+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, fds[0]);
149+ TEST_EQ (job->process_data[PROCESS_MAIN]->process, PROCESS_MAIN);
150+
151+ TEST_CHILD (job->pid[PROCESS_MAIN]) {
152+ close (fds[0]);
153+
154+ nih_error_raise_no_memory ();
155+ job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CGROUP_SETUP, 0);
156+ }
157+ close (fds[1]);
158+
159+ TEST_FREE_TAG (job);
160+
161+ job_process_handler (NULL, job->pid[PROCESS_MAIN],
162+ NIH_CHILD_DUMPED, SIGABRT);
163+
164+ TEST_NOT_FREE (job);
165+
166+ /* goal should not change until the IO handlers have had a
167+ * chance to run.
168+ */
169+ TEST_EQ (job->goal, JOB_START);
170+
171+ TEST_EQ (job->state, JOB_SPAWNED);
172+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
173+
174+ /* Still valid because the IO handlers haven't fired yet */
175+ TEST_TRUE (job->process_data[PROCESS_MAIN]->valid);
176+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, fds[0]);
177+
178+ TEST_EQ (job->process_data[PROCESS_MAIN]->shell_fd, -1);
179+ TEST_EQ_P (job->process_data[PROCESS_MAIN]->script, NULL);
180+ TEST_NE (job->process_data[PROCESS_MAIN]->status, 0);
181+
182+ /* slurp - don't care about content */
183+ buffer = read_from_fd (NULL, fds[0]);
184+ close (fds[0]);
185+
186+ nih_free (job);
187+
188+ TEST_RESET_MAIN_LOOP ();
189+
190+ /************************************************************/
191+ TEST_FEATURE ("with child setup success notification before child exit notification");
192+
193+ job = job_new (class, "");
194+ TEST_NE_P (job, NULL);
195+
196+ job->goal = JOB_START;
197+ job->state = JOB_SPAWNING;
198+
199+ assert0 (pipe (fds));
200+
201+ job->process_data[PROCESS_MAIN] = job_process_data_new (job->process_data,
202+ job, PROCESS_MAIN, fds[0]);
203+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
204+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, fds[0]);
205+ TEST_EQ (job->process_data[PROCESS_MAIN]->process, PROCESS_MAIN);
206+
207+ io = nih_io_reopen (job->process_data[PROCESS_MAIN],
208+ fds[0],
209+ NIH_IO_STREAM,
210+ (NihIoReader)job_process_child_reader,
211+ (NihIoCloseHandler)job_process_close_handler,
212+ NULL,
213+ job->process_data[PROCESS_MAIN]);
214+ TEST_NE_P (io, NULL);
215+
216+ TEST_CHILD (job->pid[PROCESS_MAIN]) {
217+ close (fds[0]);
218+
219+ nih_io_set_cloexec (fds[1]);
220+
221+ execl ("/bin/true", "/bin/true", NULL);
222+ }
223+ close (fds[1]);
224+ pid = job->pid[PROCESS_MAIN];
225+
226+ job_process_close_handler (job->process_data[PROCESS_MAIN], io);
227+
228+ TEST_EQ (job->goal, JOB_START);
229+ TEST_EQ (job->state, JOB_SPAWNED);
230+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
231+
232+ /* Invalid because the IO handlers have now run */
233+ TEST_FALSE (job->process_data[PROCESS_MAIN]->valid);
234+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, -1);
235+
236+ TEST_EQ (job->process_data[PROCESS_MAIN]->shell_fd, -1);
237+ TEST_EQ_P (job->process_data[PROCESS_MAIN]->script, NULL);
238+ TEST_EQ (job->process_data[PROCESS_MAIN]->status, 0);
239+
240+ close (fds[0]);
241+ nih_free (job);
242+
243+ (void)timed_waitpid (pid, 5);
244+
245+ TEST_RESET_MAIN_LOOP ();
246+#endif
247+
248+ /************************************************************/
249+ TEST_FEATURE ("with child setup failure notification before child exit notification");
250+
251+ job = job_new (class, "");
252+ TEST_NE_P (job, NULL);
253+
254+ job->goal = JOB_START;
255+ job->state = JOB_SPAWNING;
256+
257+ assert0 (pipe (fds));
258+
259+ job->process_data[PROCESS_MAIN] = job_process_data_new (job->process_data,
260+ job, PROCESS_MAIN, fds[0]);
261+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
262+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, fds[0]);
263+ TEST_EQ (job->process_data[PROCESS_MAIN]->process, PROCESS_MAIN);
264+
265+ /* Can't use job_register_child_handler() as we want the return
266+ * value.
267+ */
268+ io = nih_io_reopen (job->process_data[PROCESS_MAIN],
269+ fds[0],
270+ NIH_IO_STREAM,
271+ (NihIoReader)job_process_child_reader,
272+ (NihIoCloseHandler)job_process_close_handler,
273+ NULL,
274+ job->process_data[PROCESS_MAIN]);
275+ TEST_NE_P (io, NULL);
276+
277+ TEST_CHILD (job->pid[PROCESS_MAIN]) {
278+ close (fds[0]);
279+
280+ nih_error_raise_no_memory ();
281+ job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CGROUP_SETUP, 0);
282+ }
283+ close (fds[1]);
284+
285+ buffer = read_from_fd (NULL, fds[0]);
286+ job_process_child_reader (job->process_data[PROCESS_MAIN],
287+ io, buffer->buf, buffer->len);
288+
289+ TEST_EQ (job->goal, JOB_START);
290+ TEST_EQ (job->state, JOB_SPAWNED);
291+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
292+
293+ /* Invalid because the IO handlers have now run */
294+ TEST_FALSE (job->process_data[PROCESS_MAIN]->valid);
295+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, -1);
296+
297+ TEST_EQ (job->process_data[PROCESS_MAIN]->shell_fd, -1);
298+ TEST_EQ_P (job->process_data[PROCESS_MAIN]->script, NULL);
299+ TEST_EQ (job->process_data[PROCESS_MAIN]->shell_fd, -1);
300+
301+ /* Still zero because the process handler hasn't run yet */
302+ TEST_EQ (job->process_data[PROCESS_MAIN]->status, 0);
303+
304+ close (fds[0]);
305+
306+ //waitpid (job->pid[PROCESS_MAIN], &status, 0);
307+
308+ nih_free (job);
309+
310+ TEST_RESET_MAIN_LOOP ();
311+
312+ /************************************************************/
313+
314 nih_free (class);
315 file->job = NULL;
316 nih_free (source);
317
318- nih_free (event);
319- event_poll ();
320-
321 TEST_EQ (rmdir (dirname), 0);
322 TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0);
323 }
324@@ -9153,13 +9411,17 @@
325 void
326 run_tests (void)
327 {
328+#if 0
329 test_start ();
330 test_spawn ();
331 test_log_path ();
332 test_kill ();
333+#endif
334 test_handler ();
335+#if 0
336 test_utmp ();
337 test_find ();
338+#endif
339 }
340
341 /**

Subscribers

People subscribed via source and target branches