Merge lp:~jamesodhunt/upstart/async-fix-job-new-destructor into lp:upstart
- async-fix-job-new-destructor
- Merge into trunk
Proposed by
James Hunt
Status: | Superseded |
---|---|
Proposed branch: | lp:~jamesodhunt/upstart/async-fix-job-new-destructor |
Merge into: | lp:upstart |
Diff against target: |
4221 lines (+1656/-571) 17 files modified
doc/states.dot (+50/-15) init/Makefile.am (+1/-0) init/job.c (+327/-63) init/job.h (+106/-37) init/job_class.c (+2/-2) init/job_process.c (+599/-170) init/job_process.h (+40/-3) init/log.c (+2/-2) init/state.c (+2/-2) init/state.h (+1/-1) init/tests/test_event.c (+2/-2) init/tests/test_job.c (+140/-25) init/tests/test_job_process.c (+202/-244) init/tests/test_util.c (+2/-1) test/test_util_common.c (+91/-1) test/test_util_common.h (+88/-2) util/tests/test_initctl.c (+1/-1) |
To merge this branch: | bzr merge lp:~jamesodhunt/upstart/async-fix-job-new-destructor |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Dimitri John Ledkov | Pending | ||
Review via email: mp+220641@code.launchpad.net |
This proposal has been superseded by a proposal from 2014-05-22.
Commit message
Description of the change
To post a comment you must log in.
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'doc/states.dot' | |||
2 | --- doc/states.dot 2014-03-05 11:17:37 +0000 | |||
3 | +++ doc/states.dot 2014-05-22 13:31:23 +0000 | |||
4 | @@ -20,44 +20,79 @@ | |||
5 | 20 | */ | 20 | */ |
6 | 21 | 21 | ||
7 | 22 | digraph { | 22 | digraph { |
8 | 23 | rankdir=LR; | ||
9 | 24 | edge [fontsize=10]; | 23 | edge [fontsize=10]; |
10 | 25 | 24 | ||
11 | 26 | waiting [shape=diamond]; | 25 | waiting [shape=diamond]; |
12 | 27 | starting [label="starting\n(emit starting)"]; | 26 | starting [label="starting\n(emit starting)"]; |
13 | 27 | security_spawning [label="security-spawning"]; | ||
14 | 28 | security [label="security"]; | 28 | security [label="security"]; |
15 | 29 | pre_starting [label="pre-starting"]; | ||
16 | 29 | pre_start [label="pre-start"]; | 30 | pre_start [label="pre-start"]; |
17 | 31 | spawning [label="spawning"]; | ||
18 | 30 | spawned [label="spawned\n(wait for pid)"]; | 32 | spawned [label="spawned\n(wait for pid)"]; |
19 | 33 | post_starting [label="post-starting"]; | ||
20 | 31 | post_start [label="post-start"]; | 34 | post_start [label="post-start"]; |
21 | 32 | emit_started [shape=rectangle,label="emit started"]; | 35 | emit_started [shape=rectangle,label="emit started"]; |
22 | 33 | running [shape=diamond]; | 36 | running [shape=diamond]; |
23 | 37 | pre_stopping [label="pre-stopping"]; | ||
24 | 34 | pre_stop [label="pre-stop"]; | 38 | pre_stop [label="pre-stop"]; |
25 | 35 | stopping [label="stopping\n(emit stopping)"]; | 39 | stopping [label="stopping\n(emit stopping)"]; |
26 | 36 | killed [label="killed\n(wait for SIGCHLD)"]; | 40 | killed [label="killed\n(wait for SIGCHLD)"]; |
27 | 41 | post_stopping [label="post-stopping"]; | ||
28 | 37 | post_stop [label="post-stop"]; | 42 | post_stop [label="post-stop"]; |
29 | 38 | emit_stopped [shape=rectangle,label="emit stopped"]; | 43 | emit_stopped [shape=rectangle,label="emit stopped"]; |
30 | 39 | 44 | ||
34 | 40 | waiting -> starting [color=green]; | 45 | constraint=false; |
35 | 41 | starting -> security [color=green]; | 46 | waiting -> starting [color=green,weight=10]; |
36 | 42 | security -> pre_start [color=green]; | 47 | |
37 | 48 | starting -> security_spawning [color=green,weight=10]; | ||
38 | 49 | starting -> stopping [color=red]; | ||
39 | 50 | |||
40 | 51 | security_spawning -> security [color=green,weight=10]; | ||
41 | 52 | security_spawning -> stopping [color=red]; | ||
42 | 53 | |||
43 | 54 | security -> pre_starting [color=green,weight=10]; | ||
44 | 43 | security -> stopping [color=red]; | 55 | security -> stopping [color=red]; |
47 | 44 | starting -> stopping [color=red]; | 56 | |
48 | 45 | pre_start -> spawned [color=green]; | 57 | pre_starting -> pre_start [color=green,weight=10]; |
49 | 58 | pre_starting -> stopping [color=red]; | ||
50 | 59 | |||
51 | 60 | pre_start -> spawning [color=green,weight=10]; | ||
52 | 46 | pre_start -> stopping [color=red]; | 61 | pre_start -> stopping [color=red]; |
54 | 47 | spawned -> post_start [color=green]; | 62 | |
55 | 63 | spawning -> spawned [color=green,weight=10]; | ||
56 | 64 | spawning -> stopping [color=red]; | ||
57 | 65 | |||
58 | 66 | spawned -> post_starting [color=green,weight=10]; | ||
59 | 48 | spawned -> stopping [color=red]; | 67 | spawned -> stopping [color=red]; |
61 | 49 | post_start -> emit_started -> running [color=green]; | 68 | |
62 | 69 | post_starting -> post_start [color=green,weight=10]; | ||
63 | 70 | post_starting -> stopping [color=red]; | ||
64 | 71 | |||
65 | 72 | post_start -> emit_started -> running [color=green,weight=10]; | ||
66 | 50 | post_start -> stopping [color=red]; | 73 | post_start -> stopping [color=red]; |
70 | 51 | running -> pre_stop [color=red,label="pid > 0"]; | 74 | |
71 | 52 | running -> stopping [color=red,label="pid == 0"]; | 75 | running -> pre_stopping [color=red,fontcolor=red,label="pid > 0",weight=10]; |
72 | 53 | running -> stopping [color=green,label="respawn"]; | 76 | running -> stopping [color=red,fontcolor=red,label="pid == 0"]; |
73 | 77 | running -> stopping [color=green,fontcolor=darkgreen,label="respawn"]; | ||
74 | 78 | |||
75 | 79 | pre_stopping -> pre_stop [color=green,weight=10]; | ||
76 | 80 | pre_stopping -> pre_stop [color=red,weight=10]; | ||
77 | 81 | |||
78 | 54 | pre_stop -> running [color=green]; | 82 | pre_stop -> running [color=green]; |
80 | 55 | pre_stop -> stopping [color=red]; | 83 | pre_stop -> stopping [color=red,weight=10]; |
81 | 84 | |||
82 | 56 | stopping -> killed [color=green]; | 85 | stopping -> killed [color=green]; |
83 | 57 | stopping -> killed [color=red]; | 86 | stopping -> killed [color=red]; |
86 | 58 | killed -> post_stop [color=green]; | 87 | |
87 | 59 | killed -> post_stop [color=red]; | 88 | killed -> post_stopping [color=green]; |
88 | 89 | killed -> post_stopping [color=red]; | ||
89 | 90 | |||
90 | 91 | post_stopping -> post_stop [color=green,weight=10]; | ||
91 | 92 | post_stopping -> post_stop [color=red]; | ||
92 | 93 | |||
93 | 60 | post_stop -> starting [color=green]; | 94 | post_stop -> starting [color=green]; |
95 | 61 | post_stop -> emit_stopped [color=red]; | 95 | post_stop -> emit_stopped [color=red,weight=10]; |
96 | 96 | |||
97 | 62 | emit_stopped -> waiting [color=red]; | 97 | emit_stopped -> waiting [color=red]; |
98 | 63 | } | 98 | } |
99 | 64 | 99 | ||
100 | === removed file 'doc/states.png' | |||
101 | 65 | Binary files doc/states.png 2014-03-05 11:17:37 +0000 and doc/states.png 1970-01-01 00:00:00 +0000 differ | 100 | Binary files doc/states.png 2014-03-05 11:17:37 +0000 and doc/states.png 1970-01-01 00:00:00 +0000 differ |
102 | === modified file 'init/Makefile.am' | |||
103 | --- init/Makefile.am 2013-11-12 14:00:36 +0000 | |||
104 | +++ init/Makefile.am 2014-05-22 13:31:23 +0000 | |||
105 | @@ -265,6 +265,7 @@ | |||
106 | 265 | session.o log.o state.o xdg.o apparmor.o \ | 265 | session.o log.o state.o xdg.o apparmor.o \ |
107 | 266 | com.ubuntu.Upstart.o \ | 266 | com.ubuntu.Upstart.o \ |
108 | 267 | com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ | 267 | com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \ |
109 | 268 | $(top_builddir)/test/libtest_util_common.a \ | ||
110 | 268 | $(NIH_LIBS) \ | 269 | $(NIH_LIBS) \ |
111 | 269 | $(NIH_DBUS_LIBS) \ | 270 | $(NIH_DBUS_LIBS) \ |
112 | 270 | $(DBUS_LIBS) \ | 271 | $(DBUS_LIBS) \ |
113 | 271 | 272 | ||
114 | === modified file 'init/job.c' | |||
115 | --- init/job.c 2014-05-07 16:34:44 +0000 | |||
116 | +++ init/job.c 2014-05-22 13:31:23 +0000 | |||
117 | @@ -70,14 +70,6 @@ | |||
118 | 70 | __attribute__ ((warn_unused_result)); | 70 | __attribute__ ((warn_unused_result)); |
119 | 71 | 71 | ||
120 | 72 | static const char * | 72 | static const char * |
121 | 73 | job_state_enum_to_str (JobState state) | ||
122 | 74 | __attribute__ ((warn_unused_result)); | ||
123 | 75 | |||
124 | 76 | static JobState | ||
125 | 77 | job_state_str_to_enum (const char *state) | ||
126 | 78 | __attribute__ ((warn_unused_result)); | ||
127 | 79 | |||
128 | 80 | static const char * | ||
129 | 81 | job_trace_state_enum_to_str (TraceState state) | 73 | job_trace_state_enum_to_str (TraceState state) |
130 | 82 | __attribute__ ((warn_unused_result)); | 74 | __attribute__ ((warn_unused_result)); |
131 | 83 | 75 | ||
132 | @@ -93,6 +85,31 @@ | |||
133 | 93 | job_deserialise_kill_timer (json_object *json) | 85 | job_deserialise_kill_timer (json_object *json) |
134 | 94 | __attribute__ ((warn_unused_result)); | 86 | __attribute__ ((warn_unused_result)); |
135 | 95 | 87 | ||
136 | 88 | int | ||
137 | 89 | job_destroy (Job *job) | ||
138 | 90 | { | ||
139 | 91 | int i; | ||
140 | 92 | |||
141 | 93 | nih_assert (job); | ||
142 | 94 | |||
143 | 95 | /* Free any associated NihIo's to avoid the handlers getting | ||
144 | 96 | * called potentially after the job has been freed. | ||
145 | 97 | */ | ||
146 | 98 | if (job->process_data) { | ||
147 | 99 | for (i = 0; i < PROCESS_LAST; i++) { | ||
148 | 100 | if (job->process_data[i]) { | ||
149 | 101 | nih_free (job->process_data[i]); | ||
150 | 102 | |||
151 | 103 | job->process_data[i] = NULL; | ||
152 | 104 | } | ||
153 | 105 | } | ||
154 | 106 | } | ||
155 | 107 | nih_list_destroy (&job->entry); | ||
156 | 108 | |||
157 | 109 | return 0; | ||
158 | 110 | } | ||
159 | 111 | |||
160 | 112 | |||
161 | 96 | /** | 113 | /** |
162 | 97 | * job_new: | 114 | * job_new: |
163 | 98 | * @class: class of job, | 115 | * @class: class of job, |
164 | @@ -125,7 +142,10 @@ | |||
165 | 125 | 142 | ||
166 | 126 | nih_list_init (&job->entry); | 143 | nih_list_init (&job->entry); |
167 | 127 | 144 | ||
169 | 128 | nih_alloc_set_destructor (job, nih_list_destroy); | 145 | /* Ensure unset before destructor could possibly be called */ |
170 | 146 | job->process_data = NULL; | ||
171 | 147 | |||
172 | 148 | nih_alloc_set_destructor (job, job_destroy); | ||
173 | 129 | 149 | ||
174 | 130 | job->name = nih_strdup (job, name); | 150 | job->name = nih_strdup (job, name); |
175 | 131 | if (! job->name) | 151 | if (! job->name) |
176 | @@ -207,6 +227,24 @@ | |||
177 | 207 | job_register (job, conn, TRUE); | 227 | job_register (job, conn, TRUE); |
178 | 208 | } | 228 | } |
179 | 209 | 229 | ||
180 | 230 | /* Since some job processes can run in parallel, we must ensure | ||
181 | 231 | * that the asynchronous-spawning of such job processes is | ||
182 | 232 | * handled by providing a handler for each pid. | ||
183 | 233 | * | ||
184 | 234 | * Strictly, this is only necessary for certain combinations of | ||
185 | 235 | * job processes (such as PROCESS_MAIN and PROCESS_POST_START), | ||
186 | 236 | * however for consistency with other entities (such as Log), we | ||
187 | 237 | * create a slot for all job processes since there is minimal | ||
188 | 238 | * overhead (a single pointer) for those job processes tha | ||
189 | 239 | * cannot run in parallel with others. | ||
190 | 240 | */ | ||
191 | 241 | job->process_data = nih_alloc (job, sizeof (JobProcessData *) * PROCESS_LAST); | ||
192 | 242 | if (! job->process_data) | ||
193 | 243 | goto error; | ||
194 | 244 | |||
195 | 245 | for (i = 0; i < PROCESS_LAST; i++) | ||
196 | 246 | job->process_data[i] = NULL; | ||
197 | 247 | |||
198 | 210 | return job; | 248 | return job; |
199 | 211 | 249 | ||
200 | 212 | error: | 250 | error: |
201 | @@ -398,64 +436,78 @@ | |||
202 | 398 | job->blocker = job_emit_event (job); | 436 | job->blocker = job_emit_event (job); |
203 | 399 | 437 | ||
204 | 400 | break; | 438 | break; |
206 | 401 | case JOB_SECURITY: | 439 | case JOB_SECURITY_SPAWNING: |
207 | 402 | nih_assert (job->goal == JOB_START); | 440 | nih_assert (job->goal == JOB_START); |
208 | 403 | nih_assert (old_state == JOB_STARTING); | 441 | nih_assert (old_state == JOB_STARTING); |
209 | 404 | 442 | ||
210 | 405 | if (job->class->process[PROCESS_SECURITY] | 443 | if (job->class->process[PROCESS_SECURITY] |
211 | 406 | && apparmor_available()) { | 444 | && apparmor_available()) { |
218 | 407 | if (job_process_run (job, PROCESS_SECURITY) < 0) { | 445 | job_process_start (job, PROCESS_SECURITY); |
219 | 408 | job_failed (job, PROCESS_SECURITY, -1); | 446 | } |
220 | 409 | job_change_goal (job, JOB_STOP); | 447 | state = job_next_state (job); |
221 | 410 | state = job_next_state (job); | 448 | break; |
222 | 411 | } | 449 | case JOB_SECURITY: |
223 | 412 | } else { | 450 | nih_assert (job->goal == JOB_START); |
224 | 451 | nih_assert (old_state == JOB_SECURITY_SPAWNING); | ||
225 | 452 | |||
226 | 453 | if (! (job->class->process[PROCESS_SECURITY] | ||
227 | 454 | && apparmor_available())) { | ||
228 | 413 | state = job_next_state (job); | 455 | state = job_next_state (job); |
229 | 414 | } | 456 | } |
230 | 415 | |||
231 | 416 | break; | 457 | break; |
233 | 417 | case JOB_PRE_START: | 458 | case JOB_PRE_STARTING: |
234 | 418 | nih_assert (job->goal == JOB_START); | 459 | nih_assert (job->goal == JOB_START); |
235 | 419 | nih_assert (old_state == JOB_SECURITY); | 460 | nih_assert (old_state == JOB_SECURITY); |
237 | 420 | 461 | /* spawn pre-start asynchronously, child | |
238 | 462 | * watcher asynchronously will change goal to | ||
239 | 463 | * stop if spawning fails */ | ||
240 | 421 | if (job->class->process[PROCESS_PRE_START]) { | 464 | if (job->class->process[PROCESS_PRE_START]) { |
249 | 422 | if (job_process_run (job, PROCESS_PRE_START) < 0) { | 465 | job_process_start (job, PROCESS_PRE_START); |
250 | 423 | job_failed (job, PROCESS_PRE_START, -1); | 466 | } |
251 | 424 | job_change_goal (job, JOB_STOP); | 467 | state = job_next_state (job); |
252 | 425 | state = job_next_state (job); | 468 | break; |
253 | 426 | } | 469 | case JOB_PRE_START: |
254 | 427 | } else { | 470 | nih_assert (job->goal == JOB_START); |
255 | 428 | state = job_next_state (job); | 471 | nih_assert (old_state == JOB_PRE_STARTING); |
248 | 429 | } | ||
256 | 430 | 472 | ||
257 | 473 | /* if no pre-start process, go to next | ||
258 | 474 | * state. otherwise async child watcher will | ||
259 | 475 | * trigger us to go to the next state */ | ||
260 | 476 | if (! job->class->process[PROCESS_PRE_START]) | ||
261 | 477 | state = job_next_state (job); | ||
262 | 431 | break; | 478 | break; |
264 | 432 | case JOB_SPAWNED: | 479 | case JOB_SPAWNING: |
265 | 433 | nih_assert (job->goal == JOB_START); | 480 | nih_assert (job->goal == JOB_START); |
266 | 434 | nih_assert (old_state == JOB_PRE_START); | 481 | nih_assert (old_state == JOB_PRE_START); |
267 | 435 | 482 | ||
268 | 436 | if (job->class->process[PROCESS_MAIN]) { | 483 | if (job->class->process[PROCESS_MAIN]) { |
281 | 437 | if (job_process_run (job, PROCESS_MAIN) < 0) { | 484 | job_process_start (job, PROCESS_MAIN); |
282 | 438 | job_failed (job, PROCESS_MAIN, -1); | 485 | } |
283 | 439 | job_change_goal (job, JOB_STOP); | 486 | state = job_next_state (job); |
284 | 440 | state = job_next_state (job); | 487 | break; |
285 | 441 | } else if (job->class->expect == EXPECT_NONE) | 488 | case JOB_SPAWNED: |
286 | 442 | state = job_next_state (job); | 489 | nih_assert (job->goal == JOB_START); |
287 | 443 | } else { | 490 | nih_assert (old_state == JOB_SPAWNING); |
288 | 444 | state = job_next_state (job); | 491 | if (! job->class->process[PROCESS_MAIN]) { |
289 | 445 | } | 492 | state = job_next_state (job); |
290 | 446 | 493 | } | |
291 | 447 | break; | 494 | break; |
292 | 448 | case JOB_POST_START: | 495 | case JOB_POST_STARTING: |
293 | 449 | nih_assert (job->goal == JOB_START); | 496 | nih_assert (job->goal == JOB_START); |
294 | 450 | nih_assert (old_state == JOB_SPAWNED); | 497 | nih_assert (old_state == JOB_SPAWNED); |
295 | 451 | 498 | ||
296 | 452 | if (job->class->process[PROCESS_POST_START]) { | 499 | if (job->class->process[PROCESS_POST_START]) { |
300 | 453 | if (job_process_run (job, PROCESS_POST_START) < 0) | 500 | job_process_start (job, PROCESS_POST_START); |
301 | 454 | state = job_next_state (job); | 501 | } |
302 | 455 | } else { | 502 | state = job_next_state (job); |
303 | 503 | break; | ||
304 | 504 | case JOB_POST_START: | ||
305 | 505 | nih_assert (job->goal == JOB_START); | ||
306 | 506 | nih_assert (old_state == JOB_POST_STARTING); | ||
307 | 507 | |||
308 | 508 | if (! job->class->process[PROCESS_POST_START]) { | ||
309 | 456 | state = job_next_state (job); | 509 | state = job_next_state (job); |
310 | 457 | } | 510 | } |
311 | 458 | |||
312 | 459 | break; | 511 | break; |
313 | 460 | case JOB_RUNNING: | 512 | case JOB_RUNNING: |
314 | 461 | nih_assert (job->goal == JOB_START); | 513 | nih_assert (job->goal == JOB_START); |
315 | @@ -482,20 +534,26 @@ | |||
316 | 482 | } | 534 | } |
317 | 483 | 535 | ||
318 | 484 | break; | 536 | break; |
320 | 485 | case JOB_PRE_STOP: | 537 | case JOB_PRE_STOPPING: |
321 | 486 | nih_assert (job->goal == JOB_STOP); | 538 | nih_assert (job->goal == JOB_STOP); |
322 | 487 | nih_assert (old_state == JOB_RUNNING); | 539 | nih_assert (old_state == JOB_RUNNING); |
323 | 488 | 540 | ||
324 | 489 | if (job->class->process[PROCESS_PRE_STOP]) { | 541 | if (job->class->process[PROCESS_PRE_STOP]) { |
329 | 490 | if (job_process_run (job, PROCESS_PRE_STOP) < 0) | 542 | job_process_start (job, PROCESS_PRE_STOP); |
326 | 491 | state = job_next_state (job); | ||
327 | 492 | } else { | ||
328 | 493 | state = job_next_state (job); | ||
330 | 494 | } | 543 | } |
331 | 544 | state = job_next_state (job); | ||
332 | 545 | break; | ||
333 | 546 | case JOB_PRE_STOP: | ||
334 | 547 | nih_assert (job->goal == JOB_STOP); | ||
335 | 548 | nih_assert (old_state == JOB_PRE_STOPPING); | ||
336 | 495 | 549 | ||
337 | 550 | if (! job->class->process[PROCESS_PRE_STOP]) { | ||
338 | 551 | state = job_next_state (job); | ||
339 | 552 | } | ||
340 | 496 | break; | 553 | break; |
341 | 497 | case JOB_STOPPING: | 554 | case JOB_STOPPING: |
342 | 498 | nih_assert ((old_state == JOB_STARTING) | 555 | nih_assert ((old_state == JOB_STARTING) |
343 | 556 | || (old_state == JOB_PRE_STARTING) | ||
344 | 499 | || (old_state == JOB_PRE_START) | 557 | || (old_state == JOB_PRE_START) |
345 | 500 | || (old_state == JOB_SECURITY) | 558 | || (old_state == JOB_SECURITY) |
346 | 501 | || (old_state == JOB_SPAWNED) | 559 | || (old_state == JOB_SPAWNED) |
347 | @@ -508,7 +566,6 @@ | |||
348 | 508 | break; | 566 | break; |
349 | 509 | case JOB_KILLED: | 567 | case JOB_KILLED: |
350 | 510 | nih_assert (old_state == JOB_STOPPING); | 568 | nih_assert (old_state == JOB_STOPPING); |
351 | 511 | |||
352 | 512 | if (job->class->process[PROCESS_MAIN] | 569 | if (job->class->process[PROCESS_MAIN] |
353 | 513 | && (job->pid[PROCESS_MAIN] > 0)) { | 570 | && (job->pid[PROCESS_MAIN] > 0)) { |
354 | 514 | job_process_kill (job, PROCESS_MAIN); | 571 | job_process_kill (job, PROCESS_MAIN); |
355 | @@ -517,19 +574,20 @@ | |||
356 | 517 | } | 574 | } |
357 | 518 | 575 | ||
358 | 519 | break; | 576 | break; |
360 | 520 | case JOB_POST_STOP: | 577 | case JOB_POST_STOPPING: |
361 | 521 | nih_assert (old_state == JOB_KILLED); | 578 | nih_assert (old_state == JOB_KILLED); |
362 | 522 | 579 | ||
363 | 523 | if (job->class->process[PROCESS_POST_STOP]) { | 580 | if (job->class->process[PROCESS_POST_STOP]) { |
371 | 524 | if (job_process_run (job, PROCESS_POST_STOP) < 0) { | 581 | job_process_start (job, PROCESS_POST_STOP); |
365 | 525 | job_failed (job, PROCESS_POST_STOP, -1); | ||
366 | 526 | job_change_goal (job, JOB_STOP); | ||
367 | 527 | state = job_next_state (job); | ||
368 | 528 | } | ||
369 | 529 | } else { | ||
370 | 530 | state = job_next_state (job); | ||
372 | 531 | } | 582 | } |
373 | 583 | state = job_next_state (job); | ||
374 | 584 | break; | ||
375 | 585 | case JOB_POST_STOP: | ||
376 | 586 | nih_assert (old_state == JOB_POST_STOPPING); | ||
377 | 532 | 587 | ||
378 | 588 | if (! job->class->process[PROCESS_POST_STOP]) { | ||
379 | 589 | state = job_next_state (job); | ||
380 | 590 | } | ||
381 | 533 | break; | 591 | break; |
382 | 534 | case JOB_WAITING: | 592 | case JOB_WAITING: |
383 | 535 | nih_assert (job->goal == JOB_STOP); | 593 | nih_assert (job->goal == JOB_STOP); |
384 | @@ -617,6 +675,15 @@ | |||
385 | 617 | case JOB_STOP: | 675 | case JOB_STOP: |
386 | 618 | return JOB_STOPPING; | 676 | return JOB_STOPPING; |
387 | 619 | case JOB_START: | 677 | case JOB_START: |
388 | 678 | return JOB_SECURITY_SPAWNING; | ||
389 | 679 | default: | ||
390 | 680 | nih_assert_not_reached (); | ||
391 | 681 | } | ||
392 | 682 | case JOB_SECURITY_SPAWNING: | ||
393 | 683 | switch (job->goal) { | ||
394 | 684 | case JOB_STOP: | ||
395 | 685 | return JOB_STOPPING; | ||
396 | 686 | case JOB_START: | ||
397 | 620 | return JOB_SECURITY; | 687 | return JOB_SECURITY; |
398 | 621 | default: | 688 | default: |
399 | 622 | nih_assert_not_reached (); | 689 | nih_assert_not_reached (); |
400 | @@ -626,6 +693,15 @@ | |||
401 | 626 | case JOB_STOP: | 693 | case JOB_STOP: |
402 | 627 | return JOB_STOPPING; | 694 | return JOB_STOPPING; |
403 | 628 | case JOB_START: | 695 | case JOB_START: |
404 | 696 | return JOB_PRE_STARTING; | ||
405 | 697 | default: | ||
406 | 698 | nih_assert_not_reached (); | ||
407 | 699 | } | ||
408 | 700 | case JOB_PRE_STARTING: | ||
409 | 701 | switch (job->goal) { | ||
410 | 702 | case JOB_STOP: | ||
411 | 703 | return JOB_STOPPING; | ||
412 | 704 | case JOB_START: | ||
413 | 629 | return JOB_PRE_START; | 705 | return JOB_PRE_START; |
414 | 630 | default: | 706 | default: |
415 | 631 | nih_assert_not_reached (); | 707 | nih_assert_not_reached (); |
416 | @@ -635,6 +711,15 @@ | |||
417 | 635 | case JOB_STOP: | 711 | case JOB_STOP: |
418 | 636 | return JOB_STOPPING; | 712 | return JOB_STOPPING; |
419 | 637 | case JOB_START: | 713 | case JOB_START: |
420 | 714 | return JOB_SPAWNING; | ||
421 | 715 | default: | ||
422 | 716 | nih_assert_not_reached (); | ||
423 | 717 | } | ||
424 | 718 | case JOB_SPAWNING: | ||
425 | 719 | switch (job->goal) { | ||
426 | 720 | case JOB_STOP: | ||
427 | 721 | return JOB_STOPPING; | ||
428 | 722 | case JOB_START: | ||
429 | 638 | return JOB_SPAWNED; | 723 | return JOB_SPAWNED; |
430 | 639 | default: | 724 | default: |
431 | 640 | nih_assert_not_reached (); | 725 | nih_assert_not_reached (); |
432 | @@ -644,6 +729,15 @@ | |||
433 | 644 | case JOB_STOP: | 729 | case JOB_STOP: |
434 | 645 | return JOB_STOPPING; | 730 | return JOB_STOPPING; |
435 | 646 | case JOB_START: | 731 | case JOB_START: |
436 | 732 | return JOB_POST_STARTING; | ||
437 | 733 | default: | ||
438 | 734 | nih_assert_not_reached (); | ||
439 | 735 | } | ||
440 | 736 | case JOB_POST_STARTING: | ||
441 | 737 | switch (job->goal) { | ||
442 | 738 | case JOB_STOP: | ||
443 | 739 | return JOB_STOPPING; | ||
444 | 740 | case JOB_START: | ||
445 | 647 | return JOB_POST_START; | 741 | return JOB_POST_START; |
446 | 648 | default: | 742 | default: |
447 | 649 | nih_assert_not_reached (); | 743 | nih_assert_not_reached (); |
448 | @@ -665,7 +759,7 @@ | |||
449 | 665 | case JOB_STOP: | 759 | case JOB_STOP: |
450 | 666 | if (job->class->process[PROCESS_MAIN] | 760 | if (job->class->process[PROCESS_MAIN] |
451 | 667 | && (job->pid[PROCESS_MAIN] > 0)) { | 761 | && (job->pid[PROCESS_MAIN] > 0)) { |
453 | 668 | return JOB_PRE_STOP; | 762 | return JOB_PRE_STOPPING; |
454 | 669 | } else { | 763 | } else { |
455 | 670 | return JOB_STOPPING; | 764 | return JOB_STOPPING; |
456 | 671 | } | 765 | } |
457 | @@ -674,6 +768,15 @@ | |||
458 | 674 | default: | 768 | default: |
459 | 675 | nih_assert_not_reached (); | 769 | nih_assert_not_reached (); |
460 | 676 | } | 770 | } |
461 | 771 | case JOB_PRE_STOPPING: | ||
462 | 772 | switch (job->goal) { | ||
463 | 773 | case JOB_STOP: | ||
464 | 774 | return JOB_PRE_STOP; | ||
465 | 775 | case JOB_START: | ||
466 | 776 | return JOB_PRE_STOP; | ||
467 | 777 | default: | ||
468 | 778 | nih_assert_not_reached (); | ||
469 | 779 | } | ||
470 | 677 | case JOB_PRE_STOP: | 780 | case JOB_PRE_STOP: |
471 | 678 | switch (job->goal) { | 781 | switch (job->goal) { |
472 | 679 | case JOB_STOP: | 782 | case JOB_STOP: |
473 | @@ -698,6 +801,15 @@ | |||
474 | 698 | case JOB_KILLED: | 801 | case JOB_KILLED: |
475 | 699 | switch (job->goal) { | 802 | switch (job->goal) { |
476 | 700 | case JOB_STOP: | 803 | case JOB_STOP: |
477 | 804 | return JOB_POST_STOPPING; | ||
478 | 805 | case JOB_START: | ||
479 | 806 | return JOB_POST_STOPPING; | ||
480 | 807 | default: | ||
481 | 808 | nih_assert_not_reached (); | ||
482 | 809 | } | ||
483 | 810 | case JOB_POST_STOPPING: | ||
484 | 811 | switch (job->goal) { | ||
485 | 812 | case JOB_STOP: | ||
486 | 701 | return JOB_POST_STOP; | 813 | return JOB_POST_STOP; |
487 | 702 | case JOB_START: | 814 | case JOB_START: |
488 | 703 | return JOB_POST_STOP; | 815 | return JOB_POST_STOP; |
489 | @@ -870,8 +982,8 @@ | |||
490 | 870 | 982 | ||
491 | 871 | 983 | ||
492 | 872 | /** | 984 | /** |
495 | 873 | * job_emit_event: | 985 | * job_emit_event_with_state: |
496 | 874 | * @job: job generating the event. | 986 | * @job: job generating the event, |
497 | 875 | * | 987 | * |
498 | 876 | * Called from a state change because it believes an event should be | 988 | * Called from a state change because it believes an event should be |
499 | 877 | * emitted. Constructs the event with the right arguments and environment | 989 | * emitted. Constructs the event with the right arguments and environment |
500 | @@ -1100,22 +1212,34 @@ | |||
501 | 1100 | return N_("waiting"); | 1212 | return N_("waiting"); |
502 | 1101 | case JOB_STARTING: | 1213 | case JOB_STARTING: |
503 | 1102 | return N_("starting"); | 1214 | return N_("starting"); |
504 | 1215 | case JOB_SECURITY_SPAWNING: | ||
505 | 1216 | return N_("security-spawning"); | ||
506 | 1103 | case JOB_SECURITY: | 1217 | case JOB_SECURITY: |
507 | 1104 | return N_("security"); | 1218 | return N_("security"); |
508 | 1219 | case JOB_PRE_STARTING: | ||
509 | 1220 | return N_("pre-starting"); | ||
510 | 1105 | case JOB_PRE_START: | 1221 | case JOB_PRE_START: |
511 | 1106 | return N_("pre-start"); | 1222 | return N_("pre-start"); |
512 | 1223 | case JOB_SPAWNING: | ||
513 | 1224 | return N_("spawning"); | ||
514 | 1107 | case JOB_SPAWNED: | 1225 | case JOB_SPAWNED: |
515 | 1108 | return N_("spawned"); | 1226 | return N_("spawned"); |
516 | 1227 | case JOB_POST_STARTING: | ||
517 | 1228 | return N_("post-starting"); | ||
518 | 1109 | case JOB_POST_START: | 1229 | case JOB_POST_START: |
519 | 1110 | return N_("post-start"); | 1230 | return N_("post-start"); |
520 | 1111 | case JOB_RUNNING: | 1231 | case JOB_RUNNING: |
521 | 1112 | return N_("running"); | 1232 | return N_("running"); |
522 | 1233 | case JOB_PRE_STOPPING: | ||
523 | 1234 | return N_("pre-stopping"); | ||
524 | 1113 | case JOB_PRE_STOP: | 1235 | case JOB_PRE_STOP: |
525 | 1114 | return N_("pre-stop"); | 1236 | return N_("pre-stop"); |
526 | 1115 | case JOB_STOPPING: | 1237 | case JOB_STOPPING: |
527 | 1116 | return N_("stopping"); | 1238 | return N_("stopping"); |
528 | 1117 | case JOB_KILLED: | 1239 | case JOB_KILLED: |
529 | 1118 | return N_("killed"); | 1240 | return N_("killed"); |
530 | 1241 | case JOB_POST_STOPPING: | ||
531 | 1242 | return N_("post-stopping"); | ||
532 | 1119 | case JOB_POST_STOP: | 1243 | case JOB_POST_STOP: |
533 | 1120 | return N_("post-stop"); | 1244 | return N_("post-stop"); |
534 | 1121 | default: | 1245 | default: |
535 | @@ -1140,22 +1264,34 @@ | |||
536 | 1140 | return JOB_WAITING; | 1264 | return JOB_WAITING; |
537 | 1141 | } else if (! strcmp (state, "starting")) { | 1265 | } else if (! strcmp (state, "starting")) { |
538 | 1142 | return JOB_STARTING; | 1266 | return JOB_STARTING; |
539 | 1267 | } else if (! strcmp (state, "security-spawning")) { | ||
540 | 1268 | return JOB_SECURITY_SPAWNING; | ||
541 | 1143 | } else if (! strcmp (state, "security")) { | 1269 | } else if (! strcmp (state, "security")) { |
542 | 1144 | return JOB_SECURITY; | 1270 | return JOB_SECURITY; |
543 | 1271 | } else if (! strcmp (state, "pre-starting")) { | ||
544 | 1272 | return JOB_PRE_STARTING; | ||
545 | 1145 | } else if (! strcmp (state, "pre-start")) { | 1273 | } else if (! strcmp (state, "pre-start")) { |
546 | 1146 | return JOB_PRE_START; | 1274 | return JOB_PRE_START; |
547 | 1275 | } else if (! strcmp (state, "spawning")) { | ||
548 | 1276 | return JOB_SPAWNING; | ||
549 | 1147 | } else if (! strcmp (state, "spawned")) { | 1277 | } else if (! strcmp (state, "spawned")) { |
550 | 1148 | return JOB_SPAWNED; | 1278 | return JOB_SPAWNED; |
551 | 1279 | } else if (! strcmp (state, "post-starting")) { | ||
552 | 1280 | return JOB_POST_STARTING; | ||
553 | 1149 | } else if (! strcmp (state, "post-start")) { | 1281 | } else if (! strcmp (state, "post-start")) { |
554 | 1150 | return JOB_POST_START; | 1282 | return JOB_POST_START; |
555 | 1151 | } else if (! strcmp (state, "running")) { | 1283 | } else if (! strcmp (state, "running")) { |
556 | 1152 | return JOB_RUNNING; | 1284 | return JOB_RUNNING; |
557 | 1285 | } else if (! strcmp (state, "pre-stopping")) { | ||
558 | 1286 | return JOB_PRE_STOPPING; | ||
559 | 1153 | } else if (! strcmp (state, "pre-stop")) { | 1287 | } else if (! strcmp (state, "pre-stop")) { |
560 | 1154 | return JOB_PRE_STOP; | 1288 | return JOB_PRE_STOP; |
561 | 1155 | } else if (! strcmp (state, "stopping")) { | 1289 | } else if (! strcmp (state, "stopping")) { |
562 | 1156 | return JOB_STOPPING; | 1290 | return JOB_STOPPING; |
563 | 1157 | } else if (! strcmp (state, "killed")) { | 1291 | } else if (! strcmp (state, "killed")) { |
564 | 1158 | return JOB_KILLED; | 1292 | return JOB_KILLED; |
565 | 1293 | } else if (! strcmp (state, "post-stopping")) { | ||
566 | 1294 | return JOB_POST_STOPPING; | ||
567 | 1159 | } else if (! strcmp (state, "post-stop")) { | 1295 | } else if (! strcmp (state, "post-stop")) { |
568 | 1160 | return JOB_POST_STOP; | 1296 | return JOB_POST_STOP; |
569 | 1161 | } else { | 1297 | } else { |
570 | @@ -1626,6 +1762,7 @@ | |||
571 | 1626 | json_object *json_pid; | 1762 | json_object *json_pid; |
572 | 1627 | json_object *json_fds; | 1763 | json_object *json_fds; |
573 | 1628 | json_object *json_logs; | 1764 | json_object *json_logs; |
574 | 1765 | json_object *json_handler_data; | ||
575 | 1629 | 1766 | ||
576 | 1630 | nih_assert (job); | 1767 | nih_assert (job); |
577 | 1631 | 1768 | ||
578 | @@ -1771,6 +1908,33 @@ | |||
579 | 1771 | 1908 | ||
580 | 1772 | json_object_object_add (json, "log", json_logs); | 1909 | json_object_object_add (json, "log", json_logs); |
581 | 1773 | 1910 | ||
582 | 1911 | json_handler_data = json_object_new_array (); | ||
583 | 1912 | |||
584 | 1913 | if (! json_handler_data) | ||
585 | 1914 | return json; | ||
586 | 1915 | |||
587 | 1916 | for (int process = 0; process < PROCESS_LAST; process++) { | ||
588 | 1917 | json_object *json_data = NULL; | ||
589 | 1918 | |||
590 | 1919 | /* Only bother serialising if the process data hasn't | ||
591 | 1920 | * been handled yet. | ||
592 | 1921 | */ | ||
593 | 1922 | if (job->process_data[process] && job->process_data[process]->valid) { | ||
594 | 1923 | |||
595 | 1924 | json_data = job_process_data_serialise (job, | ||
596 | 1925 | job->process_data[process]); | ||
597 | 1926 | |||
598 | 1927 | if (! json_data) | ||
599 | 1928 | goto error; | ||
600 | 1929 | |||
601 | 1930 | } | ||
602 | 1931 | |||
603 | 1932 | if (json_object_array_add (json_handler_data, json_data) < 0) | ||
604 | 1933 | goto error; | ||
605 | 1934 | } | ||
606 | 1935 | |||
607 | 1936 | json_object_object_add (json, "process_data", json_handler_data); | ||
608 | 1937 | |||
609 | 1774 | return json; | 1938 | return json; |
610 | 1775 | 1939 | ||
611 | 1776 | error: | 1940 | error: |
612 | @@ -1834,6 +1998,7 @@ | |||
613 | 1834 | json_object *json_fds; | 1998 | json_object *json_fds; |
614 | 1835 | json_object *json_pid; | 1999 | json_object *json_pid; |
615 | 1836 | json_object *json_logs; | 2000 | json_object *json_logs; |
616 | 2001 | json_object *json_process_data; | ||
617 | 1837 | json_object *json_stop_on = NULL; | 2002 | json_object *json_stop_on = NULL; |
618 | 1838 | size_t len; | 2003 | size_t len; |
619 | 1839 | int ret; | 2004 | int ret; |
620 | @@ -2062,6 +2227,38 @@ | |||
621 | 2062 | } | 2227 | } |
622 | 2063 | } | 2228 | } |
623 | 2064 | 2229 | ||
624 | 2230 | |||
625 | 2231 | if (json_object_object_get_ex (json, "process_data", &json_process_data)) { | ||
626 | 2232 | if (! state_check_json_type (json_process_data, array)) | ||
627 | 2233 | goto error; | ||
628 | 2234 | |||
629 | 2235 | for (int process = 0; process < PROCESS_LAST; process++) { | ||
630 | 2236 | json_object *json_data = NULL; | ||
631 | 2237 | |||
632 | 2238 | json_data = json_object_array_get_idx (json_process_data, process); | ||
633 | 2239 | |||
634 | 2240 | if (json_data) { | ||
635 | 2241 | /* NULL if there was no process_data for this job process, or we failed to | ||
636 | 2242 | * deserialise it; either way, this should be non-fatal. | ||
637 | 2243 | */ | ||
638 | 2244 | job->process_data[process] = | ||
639 | 2245 | job_process_data_deserialise (job->process_data, job, json_data); | ||
640 | 2246 | |||
641 | 2247 | if (! job->process_data[process]) | ||
642 | 2248 | goto error; | ||
643 | 2249 | |||
644 | 2250 | /* Recreate watch */ | ||
645 | 2251 | if (job->process_data[process]->valid) { | ||
646 | 2252 | job_register_child_handler (job->process_data[process], | ||
647 | 2253 | job->process_data[process]->job_process_fd, | ||
648 | 2254 | job->process_data[process]); | ||
649 | 2255 | } | ||
650 | 2256 | } else { | ||
651 | 2257 | job->process_data[process] = NULL; | ||
652 | 2258 | } | ||
653 | 2259 | } | ||
654 | 2260 | } | ||
655 | 2261 | |||
656 | 2065 | return job; | 2262 | return job; |
657 | 2066 | 2263 | ||
658 | 2067 | error: | 2264 | error: |
659 | @@ -2163,19 +2360,25 @@ | |||
660 | 2163 | * | 2360 | * |
661 | 2164 | * Returns: string representation of @state, or NULL if not known. | 2361 | * Returns: string representation of @state, or NULL if not known. |
662 | 2165 | **/ | 2362 | **/ |
664 | 2166 | static const char * | 2363 | const char * |
665 | 2167 | job_state_enum_to_str (JobState state) | 2364 | job_state_enum_to_str (JobState state) |
666 | 2168 | { | 2365 | { |
667 | 2169 | state_enum_to_str (JOB_WAITING, state); | 2366 | state_enum_to_str (JOB_WAITING, state); |
668 | 2170 | state_enum_to_str (JOB_STARTING, state); | 2367 | state_enum_to_str (JOB_STARTING, state); |
669 | 2368 | state_enum_to_str (JOB_SECURITY_SPAWNING, state); | ||
670 | 2171 | state_enum_to_str (JOB_SECURITY, state); | 2369 | state_enum_to_str (JOB_SECURITY, state); |
671 | 2370 | state_enum_to_str (JOB_PRE_STARTING, state); | ||
672 | 2172 | state_enum_to_str (JOB_PRE_START, state); | 2371 | state_enum_to_str (JOB_PRE_START, state); |
673 | 2372 | state_enum_to_str (JOB_SPAWNING, state); | ||
674 | 2173 | state_enum_to_str (JOB_SPAWNED, state); | 2373 | state_enum_to_str (JOB_SPAWNED, state); |
675 | 2374 | state_enum_to_str (JOB_POST_STARTING, state); | ||
676 | 2174 | state_enum_to_str (JOB_POST_START, state); | 2375 | state_enum_to_str (JOB_POST_START, state); |
677 | 2175 | state_enum_to_str (JOB_RUNNING, state); | 2376 | state_enum_to_str (JOB_RUNNING, state); |
678 | 2377 | state_enum_to_str (JOB_PRE_STOPPING, state); | ||
679 | 2176 | state_enum_to_str (JOB_PRE_STOP, state); | 2378 | state_enum_to_str (JOB_PRE_STOP, state); |
680 | 2177 | state_enum_to_str (JOB_STOPPING, state); | 2379 | state_enum_to_str (JOB_STOPPING, state); |
681 | 2178 | state_enum_to_str (JOB_KILLED, state); | 2380 | state_enum_to_str (JOB_KILLED, state); |
682 | 2381 | state_enum_to_str (JOB_POST_STOPPING, state); | ||
683 | 2179 | state_enum_to_str (JOB_POST_STOP, state); | 2382 | state_enum_to_str (JOB_POST_STOP, state); |
684 | 2180 | 2383 | ||
685 | 2181 | return NULL; | 2384 | return NULL; |
686 | @@ -2190,19 +2393,25 @@ | |||
687 | 2190 | * | 2393 | * |
688 | 2191 | * Returns: JobState representation of @state, or -1 if not known. | 2394 | * Returns: JobState representation of @state, or -1 if not known. |
689 | 2192 | **/ | 2395 | **/ |
691 | 2193 | static JobState | 2396 | JobState |
692 | 2194 | job_state_str_to_enum (const char *state) | 2397 | job_state_str_to_enum (const char *state) |
693 | 2195 | { | 2398 | { |
694 | 2196 | state_str_to_enum (JOB_WAITING, state); | 2399 | state_str_to_enum (JOB_WAITING, state); |
695 | 2197 | state_str_to_enum (JOB_STARTING, state); | 2400 | state_str_to_enum (JOB_STARTING, state); |
696 | 2401 | state_str_to_enum (JOB_SECURITY_SPAWNING, state); | ||
697 | 2198 | state_str_to_enum (JOB_SECURITY, state); | 2402 | state_str_to_enum (JOB_SECURITY, state); |
698 | 2403 | state_str_to_enum (JOB_PRE_STARTING, state); | ||
699 | 2199 | state_str_to_enum (JOB_PRE_START, state); | 2404 | state_str_to_enum (JOB_PRE_START, state); |
700 | 2405 | state_str_to_enum (JOB_SPAWNING, state); | ||
701 | 2200 | state_str_to_enum (JOB_SPAWNED, state); | 2406 | state_str_to_enum (JOB_SPAWNED, state); |
702 | 2407 | state_str_to_enum (JOB_POST_STARTING, state); | ||
703 | 2201 | state_str_to_enum (JOB_POST_START, state); | 2408 | state_str_to_enum (JOB_POST_START, state); |
704 | 2202 | state_str_to_enum (JOB_RUNNING, state); | 2409 | state_str_to_enum (JOB_RUNNING, state); |
705 | 2410 | state_str_to_enum (JOB_PRE_STOPPING, state); | ||
706 | 2203 | state_str_to_enum (JOB_PRE_STOP, state); | 2411 | state_str_to_enum (JOB_PRE_STOP, state); |
707 | 2204 | state_str_to_enum (JOB_STOPPING, state); | 2412 | state_str_to_enum (JOB_STOPPING, state); |
708 | 2205 | state_str_to_enum (JOB_KILLED, state); | 2413 | state_str_to_enum (JOB_KILLED, state); |
709 | 2414 | state_str_to_enum (JOB_POST_STOPPING, state); | ||
710 | 2206 | state_str_to_enum (JOB_POST_STOP, state); | 2415 | state_str_to_enum (JOB_POST_STOP, state); |
711 | 2207 | 2416 | ||
712 | 2208 | return -1; | 2417 | return -1; |
713 | @@ -2358,3 +2567,58 @@ | |||
714 | 2358 | error: | 2567 | error: |
715 | 2359 | return NULL; | 2568 | return NULL; |
716 | 2360 | } | 2569 | } |
717 | 2570 | |||
718 | 2571 | /** | ||
719 | 2572 | * job_child_error_handler: | ||
720 | 2573 | * | ||
721 | 2574 | * @job: job, | ||
722 | 2575 | * @process: process that failed to start. | ||
723 | 2576 | * | ||
724 | 2577 | * JobProcessErrorHandler that deals with errors resulting from | ||
725 | 2578 | * a failure to start a job process. | ||
726 | 2579 | **/ | ||
727 | 2580 | void | ||
728 | 2581 | job_child_error_handler (Job *job, ProcessType process) | ||
729 | 2582 | { | ||
730 | 2583 | nih_assert (job); | ||
731 | 2584 | nih_assert (process > PROCESS_INVALID); | ||
732 | 2585 | nih_assert (process < PROCESS_LAST); | ||
733 | 2586 | |||
734 | 2587 | job->pid[process] = 0; | ||
735 | 2588 | |||
736 | 2589 | switch (process) { | ||
737 | 2590 | case PROCESS_SECURITY: | ||
738 | 2591 | job_failed (job, PROCESS_SECURITY, -1); | ||
739 | 2592 | job_change_goal (job, JOB_STOP); | ||
740 | 2593 | break; | ||
741 | 2594 | |||
742 | 2595 | case PROCESS_PRE_START: | ||
743 | 2596 | job_failed (job, PROCESS_PRE_START, -1); | ||
744 | 2597 | job_change_goal (job, JOB_STOP); | ||
745 | 2598 | job_change_state (job, job_next_state (job)); | ||
746 | 2599 | break; | ||
747 | 2600 | |||
748 | 2601 | case PROCESS_MAIN: | ||
749 | 2602 | job_failed (job, PROCESS_MAIN, -1); | ||
750 | 2603 | job_change_goal (job, JOB_STOP); | ||
751 | 2604 | job_change_state (job, job_next_state (job)); | ||
752 | 2605 | break; | ||
753 | 2606 | |||
754 | 2607 | case PROCESS_POST_START: | ||
755 | 2608 | job_change_state (job, job_next_state (job)); | ||
756 | 2609 | break; | ||
757 | 2610 | |||
758 | 2611 | case PROCESS_PRE_STOP: | ||
759 | 2612 | job_change_state (job, job_next_state (job)); | ||
760 | 2613 | break; | ||
761 | 2614 | |||
762 | 2615 | case PROCESS_POST_STOP: | ||
763 | 2616 | job_failed (job, PROCESS_POST_STOP, -1); | ||
764 | 2617 | job_change_goal (job, JOB_STOP); | ||
765 | 2618 | job_change_state (job, job_next_state (job)); | ||
766 | 2619 | break; | ||
767 | 2620 | |||
768 | 2621 | default: | ||
769 | 2622 | nih_assert_not_reached (); | ||
770 | 2623 | } | ||
771 | 2624 | } | ||
772 | 2361 | 2625 | ||
773 | === modified file 'init/job.h' | |||
774 | --- init/job.h 2013-07-22 01:24:26 +0000 | |||
775 | +++ init/job.h 2014-05-22 13:31:23 +0000 | |||
776 | @@ -1,6 +1,6 @@ | |||
777 | 1 | /* upstart | 1 | /* upstart |
778 | 2 | * | 2 | * |
780 | 3 | * Copyright © 2010 Canonical Ltd. | 3 | * Copyright 2010 Canonical Ltd. |
781 | 4 | * Author: Scott James Remnant <scott@netsplit.com>. | 4 | * Author: Scott James Remnant <scott@netsplit.com>. |
782 | 5 | * | 5 | * |
783 | 6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
784 | @@ -66,14 +66,20 @@ | |||
785 | 66 | typedef enum job_state { | 66 | typedef enum job_state { |
786 | 67 | JOB_WAITING, | 67 | JOB_WAITING, |
787 | 68 | JOB_STARTING, | 68 | JOB_STARTING, |
788 | 69 | JOB_SECURITY_SPAWNING, | ||
789 | 69 | JOB_SECURITY, | 70 | JOB_SECURITY, |
790 | 71 | JOB_PRE_STARTING, | ||
791 | 70 | JOB_PRE_START, | 72 | JOB_PRE_START, |
792 | 73 | JOB_SPAWNING, | ||
793 | 71 | JOB_SPAWNED, | 74 | JOB_SPAWNED, |
794 | 75 | JOB_POST_STARTING, | ||
795 | 72 | JOB_POST_START, | 76 | JOB_POST_START, |
796 | 73 | JOB_RUNNING, | 77 | JOB_RUNNING, |
797 | 78 | JOB_PRE_STOPPING, | ||
798 | 74 | JOB_PRE_STOP, | 79 | JOB_PRE_STOP, |
799 | 75 | JOB_STOPPING, | 80 | JOB_STOPPING, |
800 | 76 | JOB_KILLED, | 81 | JOB_KILLED, |
801 | 82 | JOB_POST_STOPPING, | ||
802 | 77 | JOB_POST_STOP | 83 | JOB_POST_STOP |
803 | 78 | } JobState; | 84 | } JobState; |
804 | 79 | 85 | ||
805 | @@ -91,6 +97,7 @@ | |||
806 | 91 | TRACE_NORMAL | 97 | TRACE_NORMAL |
807 | 92 | } TraceState; | 98 | } TraceState; |
808 | 93 | 99 | ||
809 | 100 | typedef struct job_process_data JobProcessData; | ||
810 | 94 | 101 | ||
811 | 95 | /** | 102 | /** |
812 | 96 | * Job: | 103 | * Job: |
813 | @@ -119,49 +126,102 @@ | |||
814 | 119 | * @respawn_count: number of respawns since @respawn_time, | 126 | * @respawn_count: number of respawns since @respawn_time, |
815 | 120 | * @trace_forks: number of forks traced, | 127 | * @trace_forks: number of forks traced, |
816 | 121 | * @trace_state: state of trace, | 128 | * @trace_state: state of trace, |
818 | 122 | * @log: pointer to array of log objects for handling job output. | 129 | * @log: pointer to array of log objects for handling job output, |
819 | 130 | * @process_data: transitory async job process metadata. | ||
820 | 123 | * | 131 | * |
821 | 124 | * This structure holds the state of an active job instance being tracked | 132 | * This structure holds the state of an active job instance being tracked |
822 | 125 | * by the init daemon, the configuration details of the job are available | 133 | * by the init daemon, the configuration details of the job are available |
823 | 126 | * from the @class member. | 134 | * from the @class member. |
824 | 127 | **/ | 135 | **/ |
825 | 128 | typedef struct job { | 136 | typedef struct job { |
860 | 129 | NihList entry; | 137 | NihList entry; |
861 | 130 | 138 | ||
862 | 131 | char *name; | 139 | char *name; |
863 | 132 | JobClass *class; | 140 | JobClass *class; |
864 | 133 | char *path; | 141 | char *path; |
865 | 134 | 142 | ||
866 | 135 | JobGoal goal; | 143 | JobGoal goal; |
867 | 136 | JobState state; | 144 | JobState state; |
868 | 137 | char **env; | 145 | char **env; |
869 | 138 | 146 | ||
870 | 139 | char **start_env; | 147 | char **start_env; |
871 | 140 | char **stop_env; | 148 | char **stop_env; |
872 | 141 | EventOperator *stop_on; | 149 | EventOperator *stop_on; |
873 | 142 | 150 | ||
874 | 143 | int *fds; | 151 | int *fds; |
875 | 144 | size_t num_fds; | 152 | size_t num_fds; |
876 | 145 | 153 | ||
877 | 146 | pid_t *pid; | 154 | pid_t *pid; |
878 | 147 | Event *blocker; | 155 | Event *blocker; |
879 | 148 | NihList blocking; | 156 | NihList blocking; |
880 | 149 | 157 | ||
881 | 150 | NihTimer *kill_timer; | 158 | NihTimer *kill_timer; |
882 | 151 | ProcessType kill_process; | 159 | ProcessType kill_process; |
883 | 152 | 160 | ||
884 | 153 | int failed; | 161 | int failed; |
885 | 154 | ProcessType failed_process; | 162 | ProcessType failed_process; |
886 | 155 | int exit_status; | 163 | int exit_status; |
887 | 156 | 164 | ||
888 | 157 | time_t respawn_time; | 165 | time_t respawn_time; |
889 | 158 | int respawn_count; | 166 | int respawn_count; |
890 | 159 | 167 | ||
891 | 160 | int trace_forks; | 168 | int trace_forks; |
892 | 161 | TraceState trace_state; | 169 | TraceState trace_state; |
893 | 162 | Log **log; | 170 | Log **log; |
894 | 171 | JobProcessData **process_data; | ||
895 | 172 | |||
896 | 163 | } Job; | 173 | } Job; |
897 | 164 | 174 | ||
898 | 175 | /** | ||
899 | 176 | * JobProcessData: | ||
900 | 177 | * | ||
901 | 178 | * @job: job, | ||
902 | 179 | * @process: job process to run, | ||
903 | 180 | * @script: optional script that job should run with, | ||
904 | 181 | * @shell_fd: file descriptor attached to child that @script should be | ||
905 | 182 | * written to (or -1 when @script is NULL), | ||
906 | 183 | * @job_process_fd: open readable file descriptor attached to the child | ||
907 | 184 | * process used to detect child setup errors, | ||
908 | 185 | * @status: exit status or signal in higher byte (iff | ||
909 | 186 | * job_process_terminated() ran before the job_register_child_handler() | ||
910 | 187 | * handlers), | ||
911 | 188 | * @valid: FALSE once the data has been handled, else TRUE. | ||
912 | 189 | * | ||
913 | 190 | * Used to keep track of asynchronously started job processes. | ||
914 | 191 | **/ | ||
915 | 192 | typedef struct job_process_data { | ||
916 | 193 | Job *job; | ||
917 | 194 | ProcessType process; | ||
918 | 195 | char *script; | ||
919 | 196 | int shell_fd; | ||
920 | 197 | int job_process_fd; | ||
921 | 198 | int status; | ||
922 | 199 | int valid; | ||
923 | 200 | } JobProcessData; | ||
924 | 201 | |||
925 | 202 | /** | ||
926 | 203 | * job_register_child_handler: | ||
927 | 204 | * | ||
928 | 205 | * @_parent: parent pointer, | ||
929 | 206 | * @_fd: file descriptor to monitor, | ||
930 | 207 | * @_data: data to pass to nih_io_reopen(). | ||
931 | 208 | * | ||
932 | 209 | * Register a watcher to monitor the job process child error file | ||
933 | 210 | * descriptor @_fd. | ||
934 | 211 | **/ | ||
935 | 212 | #define job_register_child_handler(_parent, _fd, _data) \ | ||
936 | 213 | while (! nih_io_reopen (_parent, _fd, NIH_IO_STREAM, \ | ||
937 | 214 | (NihIoReader)job_process_child_reader, \ | ||
938 | 215 | (NihIoCloseHandler)job_process_close_handler, \ | ||
939 | 216 | NULL, \ | ||
940 | 217 | _data)) { \ | ||
941 | 218 | NihError *err; \ | ||
942 | 219 | err = nih_error_get (); \ | ||
943 | 220 | if (err->number != ENOMEM) \ | ||
944 | 221 | nih_assert_not_reached (); \ | ||
945 | 222 | nih_free (err); \ | ||
946 | 223 | } | ||
947 | 224 | |||
948 | 165 | 225 | ||
949 | 166 | NIH_BEGIN_EXTERN | 226 | NIH_BEGIN_EXTERN |
950 | 167 | 227 | ||
951 | @@ -179,7 +239,6 @@ | |||
952 | 179 | 239 | ||
953 | 180 | Event *job_emit_event (Job *job); | 240 | Event *job_emit_event (Job *job); |
954 | 181 | 241 | ||
955 | 182 | |||
956 | 183 | const char *job_name (Job *job); | 242 | const char *job_name (Job *job); |
957 | 184 | 243 | ||
958 | 185 | const char *job_goal_name (JobGoal goal) | 244 | const char *job_goal_name (JobGoal goal) |
959 | @@ -228,6 +287,16 @@ | |||
960 | 228 | const char *job_name) | 287 | const char *job_name) |
961 | 229 | __attribute__ ((warn_unused_result)); | 288 | __attribute__ ((warn_unused_result)); |
962 | 230 | 289 | ||
963 | 290 | const char * | ||
964 | 291 | job_state_enum_to_str (JobState state) | ||
965 | 292 | __attribute__ ((warn_unused_result)); | ||
966 | 293 | |||
967 | 294 | JobState | ||
968 | 295 | job_state_str_to_enum (const char *state) | ||
969 | 296 | __attribute__ ((warn_unused_result)); | ||
970 | 297 | |||
971 | 298 | void job_child_error_handler (Job *job, ProcessType process); | ||
972 | 299 | |||
973 | 231 | NIH_END_EXTERN | 300 | NIH_END_EXTERN |
974 | 232 | 301 | ||
975 | 233 | #endif /* INIT_JOB_H */ | 302 | #endif /* INIT_JOB_H */ |
976 | 234 | 303 | ||
977 | === modified file 'init/job_class.c' | |||
978 | --- init/job_class.c 2014-05-07 16:34:44 +0000 | |||
979 | +++ init/job_class.c 2014-05-22 13:31:23 +0000 | |||
980 | @@ -2584,14 +2584,14 @@ | |||
981 | 2584 | if (fd < 0) | 2584 | if (fd < 0) |
982 | 2585 | continue; | 2585 | continue; |
983 | 2586 | 2586 | ||
985 | 2587 | if (state_toggle_cloexec (fd, FALSE) < 0) | 2587 | if (state_modify_cloexec (fd, FALSE) < 0) |
986 | 2588 | goto error; | 2588 | goto error; |
987 | 2589 | 2589 | ||
988 | 2590 | fd = log->fd; | 2590 | fd = log->fd; |
989 | 2591 | if (fd < 0) | 2591 | if (fd < 0) |
990 | 2592 | continue; | 2592 | continue; |
991 | 2593 | 2593 | ||
993 | 2594 | if (state_toggle_cloexec (fd, FALSE) < 0) | 2594 | if (state_modify_cloexec (fd, FALSE) < 0) |
994 | 2595 | goto error; | 2595 | goto error; |
995 | 2596 | } | 2596 | } |
996 | 2597 | } | 2597 | } |
997 | 2598 | 2598 | ||
998 | === modified file 'init/job_process.c' | |||
999 | --- init/job_process.c 2014-01-31 23:45:02 +0000 | |||
1000 | +++ init/job_process.c 2014-05-22 13:31:23 +0000 | |||
1001 | @@ -111,8 +111,6 @@ | |||
1002 | 111 | static void job_process_error_abort (int fd, JobProcessErrorType type, | 111 | static void job_process_error_abort (int fd, JobProcessErrorType type, |
1003 | 112 | int arg) | 112 | int arg) |
1004 | 113 | __attribute__ ((noreturn)); | 113 | __attribute__ ((noreturn)); |
1005 | 114 | static int job_process_error_read (int fd) | ||
1006 | 115 | __attribute__ ((warn_unused_result)); | ||
1007 | 116 | static void job_process_remap_fd (int *fd, int reserved_fd, int error_fd); | 114 | static void job_process_remap_fd (int *fd, int reserved_fd, int error_fd); |
1008 | 117 | 115 | ||
1009 | 118 | /** | 116 | /** |
1010 | @@ -134,7 +132,7 @@ | |||
1011 | 134 | /* Prototypes for static functions */ | 132 | /* Prototypes for static functions */ |
1012 | 135 | static void job_process_kill_timer (Job *job, NihTimer *timer); | 133 | static void job_process_kill_timer (Job *job, NihTimer *timer); |
1013 | 136 | static void job_process_terminated (Job *job, ProcessType process, | 134 | static void job_process_terminated (Job *job, ProcessType process, |
1015 | 137 | int status); | 135 | int status, int state_only); |
1016 | 138 | static int job_process_catch_runaway (Job *job); | 136 | static int job_process_catch_runaway (Job *job); |
1017 | 139 | static void job_process_stopped (Job *job, ProcessType process); | 137 | static void job_process_stopped (Job *job, ProcessType process); |
1018 | 140 | static void job_process_trace_new (Job *job, ProcessType process); | 138 | static void job_process_trace_new (Job *job, ProcessType process); |
1019 | @@ -149,8 +147,10 @@ | |||
1020 | 149 | extern int session_end; | 147 | extern int session_end; |
1021 | 150 | extern time_t quiesce_phase_time; | 148 | extern time_t quiesce_phase_time; |
1022 | 151 | 149 | ||
1023 | 150 | |||
1024 | 152 | /** | 151 | /** |
1026 | 153 | * job_process_run: | 152 | * job_process_start: |
1027 | 153 | * | ||
1028 | 154 | * @job: job context for process to be run in, | 154 | * @job: job context for process to be run in, |
1029 | 155 | * @process: job process to run. | 155 | * @process: job process to run. |
1030 | 156 | * | 156 | * |
1031 | @@ -174,27 +174,33 @@ | |||
1032 | 174 | * In either case the shell is run with the -e option so that commands will | 174 | * In either case the shell is run with the -e option so that commands will |
1033 | 175 | * fail if their exit status is not checked. | 175 | * fail if their exit status is not checked. |
1034 | 176 | * | 176 | * |
1039 | 177 | * This function will block until the job_process_spawn() call succeeds or | 177 | * This function will only block on temporary job_process_spawn_with_fd() error |
1040 | 178 | * a non-temporary error occurs (such as file not found). It is up to the | 178 | * (for example fork() failure): in normal operation it returns as soon as |
1041 | 179 | * called to decide whether non-temporary errors are a reason to change the | 179 | * the fork() was successful, registering an NihIo which provides |
1042 | 180 | * job state or not. | 180 | * asynchronous handling of the child setup stage. The specified error |
1043 | 181 | * handler will be called should child setup fail. | ||
1044 | 181 | * | 182 | * |
1046 | 182 | * Returns: zero on success, negative value on non-temporary error. | 183 | * It is up to the caller to decide whether non-temporary errors are a reason |
1047 | 184 | * to change the job state or not. | ||
1048 | 183 | **/ | 185 | **/ |
1052 | 184 | int | 186 | void |
1053 | 185 | job_process_run (Job *job, | 187 | job_process_start (Job *job, |
1054 | 186 | ProcessType process) | 188 | ProcessType process) |
1055 | 187 | { | 189 | { |
1064 | 188 | Process *proc; | 190 | Process *proc; |
1065 | 189 | nih_local char **argv = NULL; | 191 | nih_local char **argv = NULL; |
1066 | 190 | nih_local char **env = NULL; | 192 | nih_local char **env = NULL; |
1067 | 191 | nih_local char *script = NULL; | 193 | nih_local char *script = NULL; |
1068 | 192 | char **e; | 194 | char **e; |
1069 | 193 | size_t argc, envc; | 195 | size_t argc, envc; |
1070 | 194 | int fds[2] = { -1, -1 }; | 196 | int fds[2] = { -1, -1 }; |
1071 | 195 | int error = FALSE, trace = FALSE, shell = FALSE; | 197 | int trace = FALSE, shell = FALSE; |
1072 | 198 | int job_process_fd = -1; | ||
1073 | 199 | JobProcessData *process_data = NULL; | ||
1074 | 196 | 200 | ||
1076 | 197 | nih_assert (job != NULL); | 201 | nih_assert (job); |
1077 | 202 | nih_assert (process > PROCESS_INVALID); | ||
1078 | 203 | nih_assert (process < PROCESS_LAST); | ||
1079 | 198 | 204 | ||
1080 | 199 | proc = job->class->process[process]; | 205 | proc = job->class->process[process]; |
1081 | 200 | nih_assert (proc != NULL); | 206 | nih_assert (proc != NULL); |
1082 | @@ -304,35 +310,14 @@ | |||
1083 | 304 | trace = TRUE; | 310 | trace = TRUE; |
1084 | 305 | 311 | ||
1085 | 306 | /* Spawn the process, repeat until fork() works */ | 312 | /* Spawn the process, repeat until fork() works */ |
1088 | 307 | while ((job->pid[process] = job_process_spawn (job, argv, env, | 313 | while ((job->pid[process] = job_process_spawn_with_fd (job, argv, env, |
1089 | 308 | trace, fds[0], process)) < 0) { | 314 | trace, fds[0], process, &job_process_fd)) < 0) { |
1090 | 309 | NihError *err; | 315 | NihError *err; |
1091 | 310 | 316 | ||
1092 | 311 | err = nih_error_get (); | 317 | err = nih_error_get (); |
1114 | 312 | if (err->number == JOB_PROCESS_ERROR) { | 318 | nih_warn ("%s: %s", _("Temporary process spawn error"), |
1115 | 313 | /* Non-temporary error condition, we're not going | 319 | err->message); |
1095 | 314 | * to be able to spawn this process. Clean up after | ||
1096 | 315 | * ourselves before returning. | ||
1097 | 316 | */ | ||
1098 | 317 | if (shell) { | ||
1099 | 318 | close (fds[0]); | ||
1100 | 319 | close (fds[1]); | ||
1101 | 320 | } | ||
1102 | 321 | |||
1103 | 322 | job->pid[process] = 0; | ||
1104 | 323 | |||
1105 | 324 | /* Return non-temporary error condition */ | ||
1106 | 325 | nih_warn (_("Failed to spawn %s %s process: %s"), | ||
1107 | 326 | job_name (job), process_name (process), | ||
1108 | 327 | err->message); | ||
1109 | 328 | nih_free (err); | ||
1110 | 329 | return -1; | ||
1111 | 330 | } else if (! error) | ||
1112 | 331 | nih_warn ("%s: %s", _("Temporary process spawn error"), | ||
1113 | 332 | err->message); | ||
1116 | 333 | nih_free (err); | 320 | nih_free (err); |
1117 | 334 | |||
1118 | 335 | error = TRUE; | ||
1119 | 336 | } | 321 | } |
1120 | 337 | 322 | ||
1121 | 338 | nih_info (_("%s %s process (%d)"), | 323 | nih_info (_("%s %s process (%d)"), |
1122 | @@ -341,51 +326,50 @@ | |||
1123 | 341 | job->trace_forks = 0; | 326 | job->trace_forks = 0; |
1124 | 342 | job->trace_state = trace ? TRACE_NEW : TRACE_NONE; | 327 | job->trace_state = trace ? TRACE_NEW : TRACE_NONE; |
1125 | 343 | 328 | ||
1126 | 344 | /* Feed the script to the child process */ | ||
1127 | 345 | if (shell) { | 329 | if (shell) { |
1128 | 346 | NihIo *io; | ||
1129 | 347 | |||
1130 | 348 | /* Clean up and close the reading end (we don't need it) */ | 330 | /* Clean up and close the reading end (we don't need it) */ |
1131 | 349 | close (fds[0]); | 331 | close (fds[0]); |
1160 | 350 | 332 | } | |
1161 | 351 | /* Put the entire script into an NihIo send buffer and | 333 | |
1162 | 352 | * then mark it for closure so that the shell gets EOF | 334 | /* At this stage, a child process has been spawned, but may not |
1163 | 353 | * and the structure gets cleaned up automatically. | 335 | * yet have been setup appropriately. This operation is handled |
1164 | 354 | */ | 336 | * asynchronously since some setup operations may block, |
1165 | 355 | while (! (io = nih_io_reopen (job, fds[1], NIH_IO_STREAM, | 337 | * and even though they are running in a new child process, they could |
1166 | 356 | NULL, NULL, NULL, NULL))) { | 338 | * still block PID 1 since the latter needs to wait until the |
1167 | 357 | NihError *err; | 339 | * child is fully setup and the appropriate program has been |
1168 | 358 | 340 | * exec'd before marking the job as running. | |
1169 | 359 | err = nih_error_get (); | 341 | * |
1170 | 360 | if (err->number != ENOMEM) | 342 | * This is now achieved by creating an NihIo and registering |
1171 | 361 | nih_assert_not_reached (); | 343 | * appropriate handlers such that notification of successful |
1172 | 362 | nih_free (err); | 344 | * child setup and child error scenarios are handled |
1173 | 363 | } | 345 | * automatically. |
1174 | 364 | 346 | * | |
1175 | 365 | /* We're feeding using a pipe, which has a file descriptor | 347 | * job_process_child_reader() handles updating the jobs state. |
1176 | 366 | * on the child end even though it open()s it again using | 348 | */ |
1177 | 367 | * a path. Instruct the shell to close this extra fd and | 349 | process_data = job->process_data[process] = |
1178 | 368 | * not to leak it. | 350 | NIH_MUST (job_process_data_new |
1179 | 369 | */ | 351 | (job->process_data, job, process, job_process_fd)); |
1180 | 370 | NIH_ZERO (nih_io_printf (io, "exec %d<&-\n", | 352 | |
1181 | 371 | JOB_PROCESS_SCRIPT_FD)); | 353 | if (shell) { |
1182 | 372 | 354 | process_data->shell_fd = fds[1]; | |
1183 | 373 | NIH_ZERO (nih_io_write (io, script, strlen (script))); | 355 | process_data->script = script; |
1184 | 374 | nih_io_shutdown (io); | 356 | nih_ref (script, process_data); |
1185 | 375 | } | 357 | } |
1186 | 376 | 358 | ||
1187 | 377 | return 0; | 359 | /* Set up a handler to monitor the child fd asynchronously */ |
1188 | 360 | job_register_child_handler (job->process_data[process], | ||
1189 | 361 | job_process_fd, process_data); | ||
1190 | 378 | } | 362 | } |
1191 | 379 | 363 | ||
1192 | 380 | |||
1193 | 381 | /** | 364 | /** |
1195 | 382 | * job_process_spawn: | 365 | * job_process_spawn_with_fd: |
1196 | 383 | * @job: job of process to be spawned, | 366 | * @job: job of process to be spawned, |
1197 | 384 | * @argv: NULL-terminated list of arguments for the process, | 367 | * @argv: NULL-terminated list of arguments for the process, |
1198 | 385 | * @env: NULL-terminated list of environment variables for the process, | 368 | * @env: NULL-terminated list of environment variables for the process, |
1199 | 386 | * @trace: whether to trace this process, | 369 | * @trace: whether to trace this process, |
1200 | 387 | * @script_fd: script file descriptor, | 370 | * @script_fd: script file descriptor, |
1202 | 388 | * @process: job process to spawn. | 371 | * @process: job process to spawn, |
1203 | 372 | * @job_process_fd: readable child setup pipe file descriptor. | ||
1204 | 389 | * | 373 | * |
1205 | 390 | * This function spawns a new process using the class details in @job to set up | 374 | * This function spawns a new process using the class details in @job to set up |
1206 | 391 | * the environment for it; the process is always a session and process group | 375 | * the environment for it; the process is always a session and process group |
1207 | @@ -406,26 +390,30 @@ | |||
1208 | 406 | * | 390 | * |
1209 | 407 | * This function only spawns the process, it is up to the caller to ensure | 391 | * This function only spawns the process, it is up to the caller to ensure |
1210 | 408 | * that the information is saved into the job and that the process is watched, | 392 | * that the information is saved into the job and that the process is watched, |
1212 | 409 | * etc. | 393 | * etc. Also, it is up to the caller to monitor @job_process_fd to |
1213 | 394 | * ensure the child setup was successful; data available to read | ||
1214 | 395 | * indicates a failure to setup the child environment (represented by a | ||
1215 | 396 | * JOB_PROCESS_ERROR error) whereas if the descriptor is simply | ||
1216 | 397 | * closed setup was successful and the caller can then mark the job | ||
1217 | 398 | * process as started. | ||
1218 | 410 | * | 399 | * |
1219 | 411 | * Spawning a process may fail for temporary reasons, usually due to a failure | 400 | * Spawning a process may fail for temporary reasons, usually due to a failure |
1223 | 412 | * of the fork() syscall or communication with the child; or more permanent | 401 | * of the fork() syscall. |
1221 | 413 | * reasons such as a failure to setup the child environment. These latter | ||
1222 | 414 | * are always represented by a JOB_PROCESS_ERROR error. | ||
1224 | 415 | * | 402 | * |
1225 | 416 | * Returns: process id of new process on success, -1 on raised error | 403 | * Returns: process id of new process on success, -1 on raised error |
1226 | 417 | **/ | 404 | **/ |
1227 | 418 | pid_t | 405 | pid_t |
1229 | 419 | job_process_spawn (Job *job, | 406 | job_process_spawn_with_fd (Job *job, |
1230 | 420 | char * const argv[], | 407 | char * const argv[], |
1231 | 421 | char * const *env, | 408 | char * const *env, |
1232 | 422 | int trace, | 409 | int trace, |
1233 | 423 | int script_fd, | 410 | int script_fd, |
1235 | 424 | ProcessType process) | 411 | ProcessType process, |
1236 | 412 | int *job_process_fd) | ||
1237 | 425 | { | 413 | { |
1238 | 426 | sigset_t child_set, orig_set; | 414 | sigset_t child_set, orig_set; |
1239 | 427 | pid_t pid; | 415 | pid_t pid; |
1241 | 428 | int i, fds[2]; | 416 | int i, fds[2] = { -1, -1 }; |
1242 | 429 | int pty_master = -1; | 417 | int pty_master = -1; |
1243 | 430 | int pty_slave = -1; | 418 | int pty_slave = -1; |
1244 | 431 | char pts_name[PATH_MAX]; | 419 | char pts_name[PATH_MAX]; |
1245 | @@ -438,7 +426,6 @@ | |||
1246 | 438 | struct passwd *pwd = NULL; | 426 | struct passwd *pwd = NULL; |
1247 | 439 | struct group *grp = NULL; | 427 | struct group *grp = NULL; |
1248 | 440 | 428 | ||
1249 | 441 | |||
1250 | 442 | nih_assert (job != NULL); | 429 | nih_assert (job != NULL); |
1251 | 443 | nih_assert (job->class != NULL); | 430 | nih_assert (job->class != NULL); |
1252 | 444 | nih_assert (job->log != NULL); | 431 | nih_assert (job->log != NULL); |
1253 | @@ -478,7 +465,7 @@ | |||
1254 | 478 | nih_free (err); | 465 | nih_free (err); |
1255 | 479 | close (fds[0]); | 466 | close (fds[0]); |
1256 | 480 | close (fds[1]); | 467 | close (fds[1]); |
1258 | 481 | nih_return_no_memory_error(-1); | 468 | nih_return_no_memory_error (-1); |
1259 | 482 | } | 469 | } |
1260 | 483 | 470 | ||
1261 | 484 | pty_master = posix_openpt (O_RDWR | O_NOCTTY); | 471 | pty_master = posix_openpt (O_RDWR | O_NOCTTY); |
1262 | @@ -538,23 +525,10 @@ | |||
1263 | 538 | sigprocmask (SIG_SETMASK, &orig_set, NULL); | 525 | sigprocmask (SIG_SETMASK, &orig_set, NULL); |
1264 | 539 | close (fds[1]); | 526 | close (fds[1]); |
1265 | 540 | 527 | ||
1283 | 541 | /* Read error from the pipe, return if one is raised */ | 528 | *job_process_fd = fds[0]; |
1284 | 542 | if (job_process_error_read (fds[0]) < 0) { | 529 | |
1285 | 543 | if (class->console == CONSOLE_LOG) { | 530 | nih_io_set_cloexec (*job_process_fd); |
1286 | 544 | /* Ensure the pty_master watch gets | 531 | |
1270 | 545 | * removed and the fd closed. | ||
1271 | 546 | */ | ||
1272 | 547 | nih_free (job->log[process]); | ||
1273 | 548 | job->log[process] = NULL; | ||
1274 | 549 | } | ||
1275 | 550 | close (fds[0]); | ||
1276 | 551 | return -1; | ||
1277 | 552 | } | ||
1278 | 553 | |||
1279 | 554 | /* Note that pts_master is closed automatically in the parent when the | ||
1280 | 555 | * log object is destroyed. | ||
1281 | 556 | */ | ||
1282 | 557 | close (fds[0]); | ||
1287 | 558 | return pid; | 532 | return pid; |
1288 | 559 | } else if (pid < 0) { | 533 | } else if (pid < 0) { |
1289 | 560 | nih_error_raise_system (); | 534 | nih_error_raise_system (); |
1290 | @@ -923,6 +897,10 @@ | |||
1291 | 923 | * call exec below. | 897 | * call exec below. |
1292 | 924 | */ | 898 | */ |
1293 | 925 | if (class->debug) { | 899 | if (class->debug) { |
1294 | 900 | /* Since we have not exec'd at this point, we will still | ||
1295 | 901 | * have a copy of the parents fds open. As such, re-exec | ||
1296 | 902 | * will not work. | ||
1297 | 903 | */ | ||
1298 | 926 | close (fds[1]); | 904 | close (fds[1]); |
1299 | 927 | raise (SIGSTOP); | 905 | raise (SIGSTOP); |
1300 | 928 | } | 906 | } |
1301 | @@ -985,9 +963,11 @@ | |||
1302 | 985 | exit (255); | 963 | exit (255); |
1303 | 986 | } | 964 | } |
1304 | 987 | 965 | ||
1305 | 966 | |||
1306 | 988 | /** | 967 | /** |
1309 | 989 | * job_process_error_read: | 968 | * job_process_error_handler: |
1310 | 990 | * @fd: reading end of pipe. | 969 | * @buf: data read from child process, |
1311 | 970 | * @len: length of data read as @wire_err. | ||
1312 | 991 | * | 971 | * |
1313 | 992 | * Read from the reading end of the pipe specified by @fd, if we receive | 972 | * Read from the reading end of the pipe specified by @fd, if we receive |
1314 | 993 | * data then the child raised a process error which we reconstruct and raise | 973 | * data then the child raised a process error which we reconstruct and raise |
1315 | @@ -996,30 +976,26 @@ | |||
1316 | 996 | * The reconstructed error will be of JOB_PROCESS_ERROR type, the human- | 976 | * The reconstructed error will be of JOB_PROCESS_ERROR type, the human- |
1317 | 997 | * readable message is generated according to the type of process error | 977 | * readable message is generated according to the type of process error |
1318 | 998 | * and argument passed along with it. | 978 | * and argument passed along with it. |
1319 | 999 | * | ||
1320 | 1000 | * Returns: zero if no error was found, or negative value on raised error. | ||
1321 | 1001 | **/ | 979 | **/ |
1324 | 1002 | static int | 980 | void |
1325 | 1003 | job_process_error_read (int fd) | 981 | job_process_error_handler (const char *buf, size_t len) |
1326 | 1004 | { | 982 | { |
1331 | 1005 | JobProcessWireError wire_err; | 983 | JobProcessWireError *wire_err; |
1332 | 1006 | ssize_t len; | 984 | JobProcessError *err; |
1333 | 1007 | JobProcessError *err; | 985 | const char *res; |
1334 | 1008 | const char *res; | 986 | |
1335 | 987 | wire_err = (JobProcessWireError *)buf; | ||
1336 | 988 | |||
1337 | 989 | nih_assert (wire_err); | ||
1338 | 1009 | 990 | ||
1339 | 1010 | /* Read the error from the pipe; a zero read indicates that the | 991 | /* Read the error from the pipe; a zero read indicates that the |
1340 | 1011 | * exec succeeded so we return success, otherwise if we don't receive | 992 | * exec succeeded so we return success, otherwise if we don't receive |
1341 | 1012 | * a JobProcessWireError structure, we return a temporary error so we | 993 | * a JobProcessWireError structure, we return a temporary error so we |
1342 | 1013 | * try again. | 994 | * try again. |
1343 | 1014 | */ | 995 | */ |
1350 | 1015 | len = read (fd, &wire_err, sizeof (wire_err)); | 996 | if (len != sizeof (JobProcessWireError)) { |
1345 | 1016 | if (len == 0) { | ||
1346 | 1017 | return 0; | ||
1347 | 1018 | } else if (len < 0) { | ||
1348 | 1019 | nih_return_system_error (-1); | ||
1349 | 1020 | } else if (len != sizeof (wire_err)) { | ||
1351 | 1021 | errno = EILSEQ; | 997 | errno = EILSEQ; |
1353 | 1022 | nih_return_system_error (-1); | 998 | nih_return_system_error (); |
1354 | 1023 | } | 999 | } |
1355 | 1024 | 1000 | ||
1356 | 1025 | /* Construct a JobProcessError to be raised containing information | 1001 | /* Construct a JobProcessError to be raised containing information |
1357 | @@ -1028,9 +1004,9 @@ | |||
1358 | 1028 | */ | 1004 | */ |
1359 | 1029 | err = NIH_MUST (nih_new (NULL, JobProcessError)); | 1005 | err = NIH_MUST (nih_new (NULL, JobProcessError)); |
1360 | 1030 | 1006 | ||
1364 | 1031 | err->type = wire_err.type; | 1007 | err->type = wire_err->type; |
1365 | 1032 | err->arg = wire_err.arg; | 1008 | err->arg = wire_err->arg; |
1366 | 1033 | err->errnum = wire_err.errnum; | 1009 | err->errnum = wire_err->errnum; |
1367 | 1034 | 1010 | ||
1368 | 1035 | err->error.number = JOB_PROCESS_ERROR; | 1011 | err->error.number = JOB_PROCESS_ERROR; |
1369 | 1036 | 1012 | ||
1370 | @@ -1218,7 +1194,6 @@ | |||
1371 | 1218 | } | 1194 | } |
1372 | 1219 | 1195 | ||
1373 | 1220 | nih_error_raise_error (&err->error); | 1196 | nih_error_raise_error (&err->error); |
1374 | 1221 | return -1; | ||
1375 | 1222 | } | 1197 | } |
1376 | 1223 | 1198 | ||
1377 | 1224 | 1199 | ||
1378 | @@ -1332,6 +1307,7 @@ | |||
1379 | 1332 | { | 1307 | { |
1380 | 1333 | nih_assert (job); | 1308 | nih_assert (job); |
1381 | 1334 | nih_assert (timeout); | 1309 | nih_assert (timeout); |
1382 | 1310 | nih_assert (job->kill_timer == NULL); | ||
1383 | 1335 | 1311 | ||
1384 | 1336 | job->kill_process = process; | 1312 | job->kill_process = process; |
1385 | 1337 | job->kill_timer = NIH_MUST (nih_timer_add_timeout ( | 1313 | job->kill_timer = NIH_MUST (nih_timer_add_timeout ( |
1386 | @@ -1462,7 +1438,7 @@ | |||
1387 | 1462 | job_name (job), process_name (process), pid); | 1438 | job_name (job), process_name (process), pid); |
1388 | 1463 | } | 1439 | } |
1389 | 1464 | 1440 | ||
1391 | 1465 | job_process_terminated (job, process, status); | 1441 | job_process_terminated (job, process, status, FALSE); |
1392 | 1466 | break; | 1442 | break; |
1393 | 1467 | case NIH_CHILD_KILLED: | 1443 | case NIH_CHILD_KILLED: |
1394 | 1468 | case NIH_CHILD_DUMPED: | 1444 | case NIH_CHILD_DUMPED: |
1395 | @@ -1483,7 +1459,7 @@ | |||
1396 | 1483 | } | 1459 | } |
1397 | 1484 | 1460 | ||
1398 | 1485 | status <<= 8; | 1461 | status <<= 8; |
1400 | 1486 | job_process_terminated (job, process, status); | 1462 | job_process_terminated (job, process, status, FALSE); |
1401 | 1487 | break; | 1463 | break; |
1402 | 1488 | case NIH_CHILD_STOPPED: | 1464 | case NIH_CHILD_STOPPED: |
1403 | 1489 | /* Child was stopped by a signal, make sure it was SIGSTOP | 1465 | /* Child was stopped by a signal, make sure it was SIGSTOP |
1404 | @@ -1560,7 +1536,8 @@ | |||
1405 | 1560 | * job_process_terminated: | 1536 | * job_process_terminated: |
1406 | 1561 | * @job: job that changed, | 1537 | * @job: job that changed, |
1407 | 1562 | * @process: specific process, | 1538 | * @process: specific process, |
1409 | 1563 | * @status: exit status or signal in higher byte. | 1539 | * @status: exit status or signal in higher byte, |
1410 | 1540 | * @state_only: if TRUE, only update the jobs state (not its goal). | ||
1411 | 1564 | * | 1541 | * |
1412 | 1565 | * This function is called whenever a @process attached to @job terminates, | 1542 | * This function is called whenever a @process attached to @job terminates, |
1413 | 1566 | * @status should contain the exit status in the lower byte or signal in | 1543 | * @status should contain the exit status in the lower byte or signal in |
1414 | @@ -1572,7 +1549,8 @@ | |||
1415 | 1572 | static void | 1549 | static void |
1416 | 1573 | job_process_terminated (Job *job, | 1550 | job_process_terminated (Job *job, |
1417 | 1574 | ProcessType process, | 1551 | ProcessType process, |
1419 | 1575 | int status) | 1552 | int status, |
1420 | 1553 | int state_only) | ||
1421 | 1576 | { | 1554 | { |
1422 | 1577 | int failed = FALSE, stop = FALSE, state = TRUE; | 1555 | int failed = FALSE, stop = FALSE, state = TRUE; |
1423 | 1578 | struct utmpx *utmptr; | 1556 | struct utmpx *utmptr; |
1424 | @@ -1580,6 +1558,36 @@ | |||
1425 | 1580 | 1558 | ||
1426 | 1581 | nih_assert (job != NULL); | 1559 | nih_assert (job != NULL); |
1427 | 1582 | 1560 | ||
1428 | 1561 | if (job->state == JOB_SECURITY_SPAWNING || | ||
1429 | 1562 | job->state == JOB_PRE_STARTING || | ||
1430 | 1563 | job->state == JOB_SPAWNING || | ||
1431 | 1564 | job->state == JOB_POST_STARTING || | ||
1432 | 1565 | job->state == JOB_PRE_STOPPING || | ||
1433 | 1566 | job->state == JOB_POST_STOPPING) { | ||
1434 | 1567 | /* A child process has been spawned by | ||
1435 | 1568 | * job_process_spawn(), but we have not yet received | ||
1436 | 1569 | * confirmation of whether the child setup phase was | ||
1437 | 1570 | * successful or not. | ||
1438 | 1571 | * | ||
1439 | 1572 | * The fact that we are in this function means the child | ||
1440 | 1573 | * setup actually failed, however we handle that | ||
1441 | 1574 | * by waiting for the handlers registered by | ||
1442 | 1575 | * job_register_child_handler() to be called to deal | ||
1443 | 1576 | * with this error. | ||
1444 | 1577 | */ | ||
1445 | 1578 | nih_assert (job->process_data); | ||
1446 | 1579 | nih_assert (job->process_data[process]); | ||
1447 | 1580 | |||
1448 | 1581 | /* Add the child data for the *second* call to this | ||
1449 | 1582 | * function when the child pipe has been closed. | ||
1450 | 1583 | */ | ||
1451 | 1584 | job->process_data[process]->status = status; | ||
1452 | 1585 | |||
1453 | 1586 | job->state = job_next_state (job); | ||
1454 | 1587 | |||
1455 | 1588 | return; | ||
1456 | 1589 | } | ||
1457 | 1590 | |||
1458 | 1583 | switch (process) { | 1591 | switch (process) { |
1459 | 1584 | case PROCESS_MAIN: | 1592 | case PROCESS_MAIN: |
1460 | 1585 | nih_assert ((job->state == JOB_RUNNING) | 1593 | nih_assert ((job->state == JOB_RUNNING) |
1461 | @@ -1701,7 +1709,7 @@ | |||
1462 | 1701 | } | 1709 | } |
1463 | 1702 | break; | 1710 | break; |
1464 | 1703 | case PROCESS_POST_START: | 1711 | case PROCESS_POST_START: |
1466 | 1704 | nih_assert (job->state == JOB_POST_START); | 1712 | nih_assert (job->state == JOB_POST_START || job->state == JOB_RUNNING); |
1467 | 1705 | 1713 | ||
1468 | 1706 | /* We always want to change the state when the post-start | 1714 | /* We always want to change the state when the post-start |
1469 | 1707 | * script terminates; if the main process is running, we'll | 1715 | * script terminates; if the main process is running, we'll |
1470 | @@ -1750,7 +1758,7 @@ | |||
1471 | 1750 | job->kill_process = PROCESS_INVALID; | 1758 | job->kill_process = PROCESS_INVALID; |
1472 | 1751 | } | 1759 | } |
1473 | 1752 | 1760 | ||
1475 | 1753 | if (job->class->console == CONSOLE_LOG && job->log[process]) { | 1761 | if (job->class->console == CONSOLE_LOG && job->log[process] && ! state_only) { |
1476 | 1754 | int ret; | 1762 | int ret; |
1477 | 1755 | 1763 | ||
1478 | 1756 | /* It is imperative that we free the log at this stage to ensure | 1764 | /* It is imperative that we free the log at this stage to ensure |
1479 | @@ -1776,40 +1784,49 @@ | |||
1480 | 1776 | job->log[process] = NULL; | 1784 | job->log[process] = NULL; |
1481 | 1777 | } | 1785 | } |
1482 | 1778 | 1786 | ||
1505 | 1779 | /* Find existing utmp entry for the process pid */ | 1787 | if (! state_only) { |
1506 | 1780 | setutxent(); | 1788 | /* Find existing utmp entry for the process pid */ |
1507 | 1781 | while ((utmptr = getutxent()) != NULL) { | 1789 | setutxent(); |
1508 | 1782 | if (utmptr->ut_pid == job->pid[process]) { | 1790 | while ((utmptr = getutxent()) != NULL) { |
1509 | 1783 | /* set type and clean ut_user, ut_host, | 1791 | if (utmptr->ut_pid == job->pid[process]) { |
1510 | 1784 | * ut_time as described in utmp(5) | 1792 | /* set type and clean ut_user, ut_host, |
1511 | 1785 | */ | 1793 | * ut_time as described in utmp(5) |
1512 | 1786 | utmptr->ut_type = DEAD_PROCESS; | 1794 | */ |
1513 | 1787 | memset(utmptr->ut_user, 0, UT_NAMESIZE); | 1795 | utmptr->ut_type = DEAD_PROCESS; |
1514 | 1788 | memset(utmptr->ut_host, 0, UT_HOSTSIZE); | 1796 | memset(utmptr->ut_user, 0, UT_NAMESIZE); |
1515 | 1789 | utmptr->ut_time = 0; | 1797 | memset(utmptr->ut_host, 0, UT_HOSTSIZE); |
1516 | 1790 | /* Update existing utmp file. */ | 1798 | utmptr->ut_time = 0; |
1517 | 1791 | pututxline(utmptr); | 1799 | /* Update existing utmp file. */ |
1518 | 1792 | 1800 | pututxline(utmptr); | |
1519 | 1793 | /* set ut_time for log */ | 1801 | |
1520 | 1794 | gettimeofday(&tv, NULL); | 1802 | /* set ut_time for log */ |
1521 | 1795 | utmptr->ut_tv.tv_sec = tv.tv_sec; | 1803 | gettimeofday(&tv, NULL); |
1522 | 1796 | utmptr->ut_tv.tv_usec = tv.tv_usec; | 1804 | utmptr->ut_tv.tv_sec = tv.tv_sec; |
1523 | 1797 | /* Write wtmp entry */ | 1805 | utmptr->ut_tv.tv_usec = tv.tv_usec; |
1524 | 1798 | updwtmpx (_PATH_WTMP, utmptr); | 1806 | /* Write wtmp entry */ |
1525 | 1799 | 1807 | updwtmpx (_PATH_WTMP, utmptr); | |
1526 | 1800 | break; | 1808 | |
1527 | 1809 | break; | ||
1528 | 1810 | } | ||
1529 | 1801 | } | 1811 | } |
1530 | 1812 | endutxent(); | ||
1531 | 1813 | |||
1532 | 1814 | /* Clear the process pid field */ | ||
1533 | 1815 | job->pid[process] = 0; | ||
1534 | 1802 | } | 1816 | } |
1535 | 1803 | endutxent(); | ||
1536 | 1804 | |||
1537 | 1805 | /* Clear the process pid field */ | ||
1538 | 1806 | job->pid[process] = 0; | ||
1539 | 1807 | |||
1540 | 1808 | 1817 | ||
1541 | 1809 | /* Mark the job as failed */ | 1818 | /* Mark the job as failed */ |
1542 | 1810 | if (failed) | 1819 | if (failed) |
1543 | 1811 | job_failed (job, process, status); | 1820 | job_failed (job, process, status); |
1544 | 1812 | 1821 | ||
1545 | 1822 | /* Cancel goal transition if the job state only should be | ||
1546 | 1823 | * changed. | ||
1547 | 1824 | */ | ||
1548 | 1825 | if (state_only && stop) { | ||
1549 | 1826 | stop = 0; | ||
1550 | 1827 | nih_assert (! failed); | ||
1551 | 1828 | } | ||
1552 | 1829 | |||
1553 | 1813 | /* Change the goal to stop; normally this doesn't have any | 1830 | /* Change the goal to stop; normally this doesn't have any |
1554 | 1814 | * side-effects, except when we're in the RUNNING state when it'll | 1831 | * side-effects, except when we're in the RUNNING state when it'll |
1555 | 1815 | * change the state as well. We obviously don't want to change the | 1832 | * change the state as well. We obviously don't want to change the |
1556 | @@ -1887,7 +1904,7 @@ | |||
1557 | 1887 | /* Any process can stop on a signal, but we only care about the | 1904 | /* Any process can stop on a signal, but we only care about the |
1558 | 1888 | * main process when the state is still spawned. | 1905 | * main process when the state is still spawned. |
1559 | 1889 | */ | 1906 | */ |
1561 | 1890 | if ((process != PROCESS_MAIN) || (job->state != JOB_SPAWNED)) | 1907 | if ((process != PROCESS_MAIN) || ((job->state != JOB_SPAWNING) && job->state != JOB_SPAWNED)) |
1562 | 1891 | return; | 1908 | return; |
1563 | 1892 | 1909 | ||
1564 | 1893 | /* Send SIGCONT back and change the state to the next one, if this | 1910 | /* Send SIGCONT back and change the state to the next one, if this |
1565 | @@ -1916,14 +1933,16 @@ | |||
1566 | 1916 | ProcessType process) | 1933 | ProcessType process) |
1567 | 1917 | { | 1934 | { |
1568 | 1918 | nih_assert (job != NULL); | 1935 | nih_assert (job != NULL); |
1569 | 1936 | |||
1570 | 1919 | nih_assert ((job->trace_state == TRACE_NEW) | 1937 | nih_assert ((job->trace_state == TRACE_NEW) |
1571 | 1920 | || (job->trace_state == TRACE_NEW_CHILD)); | 1938 | || (job->trace_state == TRACE_NEW_CHILD)); |
1572 | 1921 | 1939 | ||
1573 | 1922 | /* Any process can get us to trace them, but we only care about the | 1940 | /* Any process can get us to trace them, but we only care about the |
1574 | 1923 | * main process when the state is still spawned. | 1941 | * main process when the state is still spawned. |
1575 | 1924 | */ | 1942 | */ |
1577 | 1925 | if ((process != PROCESS_MAIN) || (job->state != JOB_SPAWNED)) | 1943 | if ((process != PROCESS_MAIN) || ((job->state != JOB_SPAWNING) && (job->state != JOB_SPAWNED))) { |
1578 | 1926 | return; | 1944 | return; |
1579 | 1945 | } | ||
1580 | 1927 | 1946 | ||
1581 | 1928 | /* Set options so that we are notified when the process forks, and | 1947 | /* Set options so that we are notified when the process forks, and |
1582 | 1929 | * get a different kind of notification when it execs to a plain | 1948 | * get a different kind of notification when it execs to a plain |
1583 | @@ -1973,7 +1992,7 @@ | |||
1584 | 1973 | /* Any process can get us to trace them, but we only care about the | 1992 | /* Any process can get us to trace them, but we only care about the |
1585 | 1974 | * main process when the state is still spawned. | 1993 | * main process when the state is still spawned. |
1586 | 1975 | */ | 1994 | */ |
1588 | 1976 | if ((process != PROCESS_MAIN) || (job->state != JOB_SPAWNED)) | 1995 | if ((process != PROCESS_MAIN) || ((job->state != JOB_SPAWNING) && (job->state != JOB_SPAWNED))) |
1589 | 1977 | return; | 1996 | return; |
1590 | 1978 | 1997 | ||
1591 | 1979 | /* We need to fork at least twice unless we're expecting a | 1998 | /* We need to fork at least twice unless we're expecting a |
1592 | @@ -2018,7 +2037,7 @@ | |||
1593 | 2018 | /* Any process can get us to trace them, but we only care about the | 2037 | /* Any process can get us to trace them, but we only care about the |
1594 | 2019 | * main process when the state is still spawned. | 2038 | * main process when the state is still spawned. |
1595 | 2020 | */ | 2039 | */ |
1597 | 2021 | if ((process != PROCESS_MAIN) || (job->state != JOB_SPAWNED) | 2040 | if ((process != PROCESS_MAIN) || ((job->state != JOB_SPAWNING) && (job->state != JOB_SPAWNED)) |
1598 | 2022 | || (job->trace_state != TRACE_NORMAL)) | 2041 | || (job->trace_state != TRACE_NORMAL)) |
1599 | 2023 | return; | 2042 | return; |
1600 | 2024 | 2043 | ||
1601 | @@ -2053,9 +2072,10 @@ | |||
1602 | 2053 | /* Any process can get us to trace them, but we only care about the | 2072 | /* Any process can get us to trace them, but we only care about the |
1603 | 2054 | * main process when the state is still spawned. | 2073 | * main process when the state is still spawned. |
1604 | 2055 | */ | 2074 | */ |
1607 | 2056 | if ((process != PROCESS_MAIN) || (job->state != JOB_SPAWNED) | 2075 | if ((process != PROCESS_MAIN) || ((job->state != JOB_SPAWNING) && (job->state != JOB_SPAWNED)) |
1608 | 2057 | || (job->trace_state != TRACE_NORMAL)) | 2076 | || (job->trace_state != TRACE_NORMAL)) { |
1609 | 2058 | return; | 2077 | return; |
1610 | 2078 | } | ||
1611 | 2059 | 2079 | ||
1612 | 2060 | /* Obtain the child process id from the ptrace event. */ | 2080 | /* Obtain the child process id from the ptrace event. */ |
1613 | 2061 | if (ptrace (PTRACE_GETEVENTMSG, job->pid[process], NULL, &data) < 0) { | 2081 | if (ptrace (PTRACE_GETEVENTMSG, job->pid[process], NULL, &data) < 0) { |
1614 | @@ -2121,7 +2141,7 @@ | |||
1615 | 2121 | /* Any process can get us to trace them, but we only care about the | 2141 | /* Any process can get us to trace them, but we only care about the |
1616 | 2122 | * main process when the state is still spawned and we're tracing it. | 2142 | * main process when the state is still spawned and we're tracing it. |
1617 | 2123 | */ | 2143 | */ |
1619 | 2124 | if ((process != PROCESS_MAIN) || (job->state != JOB_SPAWNED) | 2144 | if ((process != PROCESS_MAIN) || ((job->state != JOB_SPAWNING) && job->state != JOB_SPAWNED) |
1620 | 2125 | || (job->trace_state != TRACE_NORMAL)) | 2145 | || (job->trace_state != TRACE_NORMAL)) |
1621 | 2126 | return; | 2146 | return; |
1622 | 2127 | 2147 | ||
1623 | @@ -2176,7 +2196,6 @@ | |||
1624 | 2176 | if (job->pid[i] == pid) { | 2196 | if (job->pid[i] == pid) { |
1625 | 2177 | if (process) | 2197 | if (process) |
1626 | 2178 | *process = i; | 2198 | *process = i; |
1627 | 2179 | |||
1628 | 2180 | return job; | 2199 | return job; |
1629 | 2181 | } | 2200 | } |
1630 | 2182 | } | 2201 | } |
1631 | @@ -2315,16 +2334,426 @@ | |||
1632 | 2315 | 2334 | ||
1633 | 2316 | nih_assert (fd); | 2335 | nih_assert (fd); |
1634 | 2317 | nih_assert (reserved_fd); | 2336 | nih_assert (reserved_fd); |
1636 | 2318 | nih_assert (error_fd); | 2337 | nih_assert (error_fd >= 0); |
1637 | 2319 | 2338 | ||
1639 | 2320 | if (*fd != reserved_fd) | 2339 | if (*fd != reserved_fd) { |
1640 | 2340 | /* fd does not need remapping */ | ||
1641 | 2321 | return; | 2341 | return; |
1642 | 2342 | } | ||
1643 | 2322 | 2343 | ||
1644 | 2323 | new = dup (*fd); | 2344 | new = dup (*fd); |
1645 | 2324 | if (new < 0) { | 2345 | if (new < 0) { |
1646 | 2325 | nih_error_raise_system (); | 2346 | nih_error_raise_system (); |
1647 | 2326 | job_process_error_abort (error_fd, JOB_PROCESS_ERROR_DUP, 0); | 2347 | job_process_error_abort (error_fd, JOB_PROCESS_ERROR_DUP, 0); |
1648 | 2327 | } | 2348 | } |
1649 | 2349 | |||
1650 | 2328 | close (*fd); | 2350 | close (*fd); |
1651 | 2329 | *fd = new; | 2351 | *fd = new; |
1652 | 2330 | } | 2352 | } |
1653 | 2353 | |||
1654 | 2354 | |||
1655 | 2355 | /** | ||
1656 | 2356 | * job_process_child_reader: | ||
1657 | 2357 | * | ||
1658 | 2358 | * @process_data: JobProcessHandlerData structure, | ||
1659 | 2359 | * @io: NihIo with data to be read, | ||
1660 | 2360 | * @buf: buffer data is available in, | ||
1661 | 2361 | * @len: bytes in @buf. | ||
1662 | 2362 | * | ||
1663 | 2363 | * Called automatically when an error occurred setting up the child process. | ||
1664 | 2364 | **/ | ||
1665 | 2365 | void | ||
1666 | 2366 | job_process_child_reader (JobProcessData *process_data, | ||
1667 | 2367 | NihIo *io, | ||
1668 | 2368 | const char *buf, | ||
1669 | 2369 | size_t len) | ||
1670 | 2370 | { | ||
1671 | 2371 | Job *job; | ||
1672 | 2372 | ProcessType process; | ||
1673 | 2373 | NihError *err; | ||
1674 | 2374 | |||
1675 | 2375 | /* The job is in the process of being killed which must mean all | ||
1676 | 2376 | * the job pids are dead. Hence, there is no point in attempting | ||
1677 | 2377 | * to talk to them. | ||
1678 | 2378 | */ | ||
1679 | 2379 | if (! process_data) | ||
1680 | 2380 | return; | ||
1681 | 2381 | if (! process_data->valid) | ||
1682 | 2382 | return; | ||
1683 | 2383 | |||
1684 | 2384 | nih_assert (io); | ||
1685 | 2385 | nih_assert (buf); | ||
1686 | 2386 | |||
1687 | 2387 | job = process_data->job; | ||
1688 | 2388 | process = process_data->process; | ||
1689 | 2389 | |||
1690 | 2390 | /* Construct the NIH error from the data received from | ||
1691 | 2391 | * the child. | ||
1692 | 2392 | */ | ||
1693 | 2393 | job_process_error_handler (buf, len); | ||
1694 | 2394 | |||
1695 | 2395 | err = nih_error_get (); | ||
1696 | 2396 | |||
1697 | 2397 | nih_assert (err->number == JOB_PROCESS_ERROR); | ||
1698 | 2398 | |||
1699 | 2399 | /* Non-temporary error condition */ | ||
1700 | 2400 | nih_warn (_("Failed to spawn %s %s process: %s"), | ||
1701 | 2401 | job_name (job), process_name (process), | ||
1702 | 2402 | err->message); | ||
1703 | 2403 | nih_free (err); | ||
1704 | 2404 | |||
1705 | 2405 | /* Non-temporary error condition, we're not going | ||
1706 | 2406 | * to be able to spawn this job. | ||
1707 | 2407 | */ | ||
1708 | 2408 | if (process_data->shell_fd != -1) { | ||
1709 | 2409 | close (process_data->shell_fd); | ||
1710 | 2410 | |||
1711 | 2411 | /* Invalidate */ | ||
1712 | 2412 | process_data->shell_fd = -1; | ||
1713 | 2413 | } | ||
1714 | 2414 | |||
1715 | 2415 | if (job && job->class->console == CONSOLE_LOG && job->log[process]) { | ||
1716 | 2416 | /* Ensure the pty_master watch gets | ||
1717 | 2417 | * removed and the fd closed. | ||
1718 | 2418 | */ | ||
1719 | 2419 | nih_free (job->log[process]); | ||
1720 | 2420 | job->log[process] = NULL; | ||
1721 | 2421 | } | ||
1722 | 2422 | |||
1723 | 2423 | /* Now call the handler registered via job_process_start() | ||
1724 | 2424 | * to deal with the error condition. | ||
1725 | 2425 | */ | ||
1726 | 2426 | job_child_error_handler (job, process); | ||
1727 | 2427 | |||
1728 | 2428 | /* Note that pts_master is closed automatically in the parent | ||
1729 | 2429 | * when the log object is destroyed. | ||
1730 | 2430 | */ | ||
1731 | 2431 | |||
1732 | 2432 | nih_io_shutdown (io); | ||
1733 | 2433 | |||
1734 | 2434 | /* Invalidate */ | ||
1735 | 2435 | process_data->job_process_fd = -1; | ||
1736 | 2436 | process_data->valid = FALSE; | ||
1737 | 2437 | } | ||
1738 | 2438 | |||
1739 | 2439 | /** | ||
1740 | 2440 | * @process_data: JobProcessData, | ||
1741 | 2441 | * @io: NihIo. | ||
1742 | 2442 | * | ||
1743 | 2443 | * NihIoCloseHandler called when job process starts successfully. | ||
1744 | 2444 | **/ | ||
1745 | 2445 | void | ||
1746 | 2446 | job_process_close_handler (JobProcessData *process_data, | ||
1747 | 2447 | NihIo *io) | ||
1748 | 2448 | { | ||
1749 | 2449 | Job *job; | ||
1750 | 2450 | ProcessType process; | ||
1751 | 2451 | int status; | ||
1752 | 2452 | |||
1753 | 2453 | /* The job is in the process of being killed which must mean all | ||
1754 | 2454 | * the job pids are dead. Hence, there is no point in attempting | ||
1755 | 2455 | * to talk to them. | ||
1756 | 2456 | */ | ||
1757 | 2457 | if (! process_data) | ||
1758 | 2458 | return; | ||
1759 | 2459 | |||
1760 | 2460 | nih_assert (io); | ||
1761 | 2461 | |||
1762 | 2462 | job = process_data->job; | ||
1763 | 2463 | process = process_data->process; | ||
1764 | 2464 | status = process_data->status; | ||
1765 | 2465 | |||
1766 | 2466 | /* Ensure the job process error fd is closed before attempting | ||
1767 | 2467 | * to handle any scripts. | ||
1768 | 2468 | */ | ||
1769 | 2469 | nih_free (io); | ||
1770 | 2470 | |||
1771 | 2471 | /* invalidate */ | ||
1772 | 2472 | process_data->job_process_fd = -1; | ||
1773 | 2473 | process_data->valid = FALSE; | ||
1774 | 2474 | |||
1775 | 2475 | job_process_run_bottom (process_data); | ||
1776 | 2476 | |||
1777 | 2477 | if (job && job->state == JOB_SPAWNED) { | ||
1778 | 2478 | if (job->class->expect == EXPECT_NONE) { | ||
1779 | 2479 | nih_assert (process == PROCESS_MAIN); | ||
1780 | 2480 | job_change_state (job, job_next_state (job)); | ||
1781 | 2481 | } | ||
1782 | 2482 | } | ||
1783 | 2483 | |||
1784 | 2484 | /* Don't change the jobs goal yet as the process may not have | ||
1785 | 2485 | * actually terminted (and hence will have | ||
1786 | 2486 | * job_process_terminated() called on it again later). | ||
1787 | 2487 | */ | ||
1788 | 2488 | switch (job->state) { | ||
1789 | 2489 | /* FIXME: BUG: incomplete list of states!!!! */ | ||
1790 | 2490 | case JOB_SECURITY_SPAWNING: | ||
1791 | 2491 | case JOB_PRE_STARTING: | ||
1792 | 2492 | case JOB_SPAWNING: | ||
1793 | 2493 | case JOB_POST_STARTING: | ||
1794 | 2494 | case JOB_PRE_STOPPING: | ||
1795 | 2495 | case JOB_POST_STOPPING: | ||
1796 | 2496 | job_process_terminated (job, process, status, TRUE); | ||
1797 | 2497 | break; | ||
1798 | 2498 | |||
1799 | 2499 | default: | ||
1800 | 2500 | /* NOP */ | ||
1801 | 2501 | break; | ||
1802 | 2502 | } | ||
1803 | 2503 | } | ||
1804 | 2504 | |||
1805 | 2505 | |||
1806 | 2506 | /** | ||
1807 | 2507 | * job_process_run_bottom: | ||
1808 | 2508 | * | ||
1809 | 2509 | * @process_data: JobProcessData. | ||
1810 | 2510 | * | ||
1811 | 2511 | * Perform final job process setup. | ||
1812 | 2512 | **/ | ||
1813 | 2513 | void | ||
1814 | 2514 | job_process_run_bottom (JobProcessData *process_data) | ||
1815 | 2515 | { | ||
1816 | 2516 | Job *job; | ||
1817 | 2517 | //JobState state; | ||
1818 | 2518 | char *script; | ||
1819 | 2519 | int shell_fd; | ||
1820 | 2520 | |||
1821 | 2521 | nih_assert (process_data); | ||
1822 | 2522 | |||
1823 | 2523 | job = process_data->job; | ||
1824 | 2524 | shell_fd = process_data->shell_fd; | ||
1825 | 2525 | script = process_data->script; | ||
1826 | 2526 | //state = process_data->state; | ||
1827 | 2527 | |||
1828 | 2528 | /* Handle job process containing a script section by sending the | ||
1829 | 2529 | * script to the child shell. | ||
1830 | 2530 | */ | ||
1831 | 2531 | if (script && shell_fd != -1) { | ||
1832 | 2532 | NihIo *io; | ||
1833 | 2533 | |||
1834 | 2534 | |||
1835 | 2535 | /* Put the entire script into an NihIo send buffer and | ||
1836 | 2536 | * then mark it for closure so that the shell gets EOF | ||
1837 | 2537 | * and the structure gets cleaned up automatically. | ||
1838 | 2538 | */ | ||
1839 | 2539 | while (! (io = nih_io_reopen (job, shell_fd, NIH_IO_STREAM, | ||
1840 | 2540 | NULL, NULL, NULL, NULL))) { | ||
1841 | 2541 | NihError *err; | ||
1842 | 2542 | |||
1843 | 2543 | err = nih_error_get (); | ||
1844 | 2544 | |||
1845 | 2545 | if (err->number != ENOMEM) | ||
1846 | 2546 | nih_assert_not_reached (); | ||
1847 | 2547 | nih_free (err); | ||
1848 | 2548 | } | ||
1849 | 2549 | |||
1850 | 2550 | /* We're feeding using a pipe, which has a file descriptor | ||
1851 | 2551 | * on the child end even though it open()s it again using | ||
1852 | 2552 | * a path. Instruct the shell to close this extra fd and | ||
1853 | 2553 | * not to leak it. | ||
1854 | 2554 | */ | ||
1855 | 2555 | NIH_ZERO (nih_io_printf (io, "exec %d<&-\n", | ||
1856 | 2556 | JOB_PROCESS_SCRIPT_FD)); | ||
1857 | 2557 | |||
1858 | 2558 | NIH_ZERO (nih_io_write (io, script, strlen (script))); | ||
1859 | 2559 | |||
1860 | 2560 | /* We're only using the io for writing, so clear the | ||
1861 | 2561 | * default flag. | ||
1862 | 2562 | */ | ||
1863 | 2563 | io->watch->events &= ~NIH_IO_READ; | ||
1864 | 2564 | |||
1865 | 2565 | nih_io_shutdown (io); | ||
1866 | 2566 | |||
1867 | 2567 | /* Invalidate now that we've sent the script to the | ||
1868 | 2568 | * child. | ||
1869 | 2569 | */ | ||
1870 | 2570 | process_data->shell_fd = -1; | ||
1871 | 2571 | process_data->valid = FALSE; | ||
1872 | 2572 | } | ||
1873 | 2573 | |||
1874 | 2574 | /* Success, so change the job state */ | ||
1875 | 2575 | //job->state = state; | ||
1876 | 2576 | //job->state = job_next_state (job); | ||
1877 | 2577 | |||
1878 | 2578 | NIH_LIST_FOREACH (control_conns, iter) { | ||
1879 | 2579 | NihListEntry *entry = (NihListEntry *)iter; | ||
1880 | 2580 | DBusConnection *conn = (DBusConnection *)entry->data; | ||
1881 | 2581 | |||
1882 | 2582 | NIH_ZERO (job_emit_state_changed ( | ||
1883 | 2583 | conn, job->path, | ||
1884 | 2584 | job_state_name (job->state))); | ||
1885 | 2585 | } | ||
1886 | 2586 | } | ||
1887 | 2587 | |||
1888 | 2588 | |||
1889 | 2589 | /** | ||
1890 | 2590 | * job_process_data_new: | ||
1891 | 2591 | * | ||
1892 | 2592 | * @parent: parent pointer, | ||
1893 | 2593 | * @job: job, | ||
1894 | 2594 | * @process: currently-running job process, | ||
1895 | 2595 | * @job_process_fd: error file descriptor connected to job process used | ||
1896 | 2596 | * to signal successful job process setup. | ||
1897 | 2597 | * | ||
1898 | 2598 | * Create a new job process data object to record meta-data for an | ||
1899 | 2599 | * asynchronously-started job process. The lifetime of such objects is | ||
1900 | 2600 | * limited to the time taken for the job process to fail or indicate | ||
1901 | 2601 | * successful startup (both scenarios are handled by @job_process_fd). | ||
1902 | 2602 | * | ||
1903 | 2603 | * Returns: Newly-allocated JobProcess on success, or NULL on | ||
1904 | 2604 | * insufficient memory. | ||
1905 | 2605 | **/ | ||
1906 | 2606 | JobProcessData * | ||
1907 | 2607 | job_process_data_new (void *parent, | ||
1908 | 2608 | Job *job, | ||
1909 | 2609 | ProcessType process, | ||
1910 | 2610 | int job_process_fd) | ||
1911 | 2611 | { | ||
1912 | 2612 | JobProcessData *process_data; | ||
1913 | 2613 | |||
1914 | 2614 | nih_assert (job); | ||
1915 | 2615 | nih_assert (job_process_fd != -1); | ||
1916 | 2616 | |||
1917 | 2617 | process_data = NIH_MUST (nih_new (parent, JobProcessData)); | ||
1918 | 2618 | if (! process_data) | ||
1919 | 2619 | return NULL; | ||
1920 | 2620 | |||
1921 | 2621 | process_data->process = process; | ||
1922 | 2622 | process_data->job_process_fd = job_process_fd; | ||
1923 | 2623 | |||
1924 | 2624 | process_data->script = NULL; | ||
1925 | 2625 | process_data->shell_fd = -1; | ||
1926 | 2626 | process_data->valid = TRUE; | ||
1927 | 2627 | |||
1928 | 2628 | process_data->job = job; | ||
1929 | 2629 | process_data->status = 0; | ||
1930 | 2630 | |||
1931 | 2631 | return process_data; | ||
1932 | 2632 | } | ||
1933 | 2633 | |||
1934 | 2634 | /** | ||
1935 | 2635 | * job_process_data_serialise: | ||
1936 | 2636 | * | ||
1937 | 2637 | * @job: job, | ||
1938 | 2638 | * @process_data: job process data. | ||
1939 | 2639 | * | ||
1940 | 2640 | * Returns: JSON-serialised JobProcessData object, or NULL on error. | ||
1941 | 2641 | **/ | ||
1942 | 2642 | json_object * | ||
1943 | 2643 | job_process_data_serialise (const Job *job, const JobProcessData *process_data) | ||
1944 | 2644 | { | ||
1945 | 2645 | json_object *json; | ||
1946 | 2646 | |||
1947 | 2647 | nih_assert (job); | ||
1948 | 2648 | |||
1949 | 2649 | json = json_object_new_object (); | ||
1950 | 2650 | if (! json) | ||
1951 | 2651 | return NULL; | ||
1952 | 2652 | |||
1953 | 2653 | /* Job has no "in-flight" process */ | ||
1954 | 2654 | if (! process_data) | ||
1955 | 2655 | return json; | ||
1956 | 2656 | |||
1957 | 2657 | /* XXX: Note that Job is not serialised; it's not necessary | ||
1958 | 2658 | * since the JobProcessData itself is serialised within its Job | ||
1959 | 2659 | * and the job pointer can be reinstated on deserialisation. | ||
1960 | 2660 | */ | ||
1961 | 2661 | |||
1962 | 2662 | if (! state_set_json_enum_var (json, | ||
1963 | 2663 | process_type_enum_to_str, | ||
1964 | 2664 | "process", process_data->process)) | ||
1965 | 2665 | goto error; | ||
1966 | 2666 | |||
1967 | 2667 | if (! state_set_json_string_var_from_obj (json, process_data, script)) | ||
1968 | 2668 | goto error; | ||
1969 | 2669 | |||
1970 | 2670 | if (process_data->shell_fd != -1 && process_data->valid) { | ||
1971 | 2671 | |||
1972 | 2672 | /* Clear the cloexec flag to ensure the descriptors | ||
1973 | 2673 | * remains open across the re-exec. | ||
1974 | 2674 | */ | ||
1975 | 2675 | if (state_modify_cloexec (process_data->shell_fd, FALSE) < 0) | ||
1976 | 2676 | goto error; | ||
1977 | 2677 | |||
1978 | 2678 | if (state_modify_cloexec (process_data->job_process_fd, FALSE) < 0) | ||
1979 | 2679 | goto error; | ||
1980 | 2680 | } | ||
1981 | 2681 | |||
1982 | 2682 | if (! state_set_json_int_var_from_obj (json, process_data, shell_fd)) | ||
1983 | 2683 | goto error; | ||
1984 | 2684 | |||
1985 | 2685 | if (! state_set_json_int_var_from_obj (json, process_data, valid)) | ||
1986 | 2686 | goto error; | ||
1987 | 2687 | |||
1988 | 2688 | if (! state_set_json_int_var_from_obj (json, process_data, job_process_fd)) | ||
1989 | 2689 | goto error; | ||
1990 | 2690 | |||
1991 | 2691 | return json; | ||
1992 | 2692 | |||
1993 | 2693 | error: | ||
1994 | 2694 | json_object_put (json); | ||
1995 | 2695 | return NULL; | ||
1996 | 2696 | } | ||
1997 | 2697 | |||
1998 | 2698 | /** | ||
1999 | 2699 | * job_process_data_deserialise: | ||
2000 | 2700 | * | ||
2001 | 2701 | * @parent: parent pointer, | ||
2002 | 2702 | * @job: job, | ||
2003 | 2703 | * @json: JSON-serialised JobProcessData object to deserialise. | ||
2004 | 2704 | * | ||
2005 | 2705 | * Returns: JobProcessData object, or NULL on error. | ||
2006 | 2706 | **/ | ||
2007 | 2707 | JobProcessData * | ||
2008 | 2708 | job_process_data_deserialise (void *parent, Job *job, json_object *json) | ||
2009 | 2709 | { | ||
2010 | 2710 | JobProcessData *process_data = NULL; | ||
2011 | 2711 | ProcessType process; | ||
2012 | 2712 | int job_process_fd; | ||
2013 | 2713 | |||
2014 | 2714 | nih_assert (job); | ||
2015 | 2715 | nih_assert (json); | ||
2016 | 2716 | |||
2017 | 2717 | if (! state_check_json_type (json, object)) | ||
2018 | 2718 | return NULL; | ||
2019 | 2719 | |||
2020 | 2720 | if (! state_get_json_enum_var (json, | ||
2021 | 2721 | process_type_str_to_enum, | ||
2022 | 2722 | "process", process)) | ||
2023 | 2723 | return NULL; | ||
2024 | 2724 | |||
2025 | 2725 | if (! state_get_json_int_var (json, "job_process_fd", job_process_fd)) | ||
2026 | 2726 | return NULL; | ||
2027 | 2727 | |||
2028 | 2728 | process_data = job_process_data_new (parent, job, process, job_process_fd); | ||
2029 | 2729 | if (! process_data) | ||
2030 | 2730 | return NULL; | ||
2031 | 2731 | |||
2032 | 2732 | if (! state_get_json_string_var_to_obj (json, process_data, script)) | ||
2033 | 2733 | goto error; | ||
2034 | 2734 | |||
2035 | 2735 | if (! state_get_json_int_var_to_obj (json, process_data, shell_fd)) | ||
2036 | 2736 | goto error; | ||
2037 | 2737 | |||
2038 | 2738 | if (! state_get_json_int_var_to_obj (json, process_data, valid)) | ||
2039 | 2739 | goto error; | ||
2040 | 2740 | |||
2041 | 2741 | if (process_data->shell_fd != -1 && process_data->valid) { | ||
2042 | 2742 | /* Reset the cloexec flag to ensure the descriptors | ||
2043 | 2743 | * are not leaked to any child processes. | ||
2044 | 2744 | */ | ||
2045 | 2745 | if (state_modify_cloexec (process_data->shell_fd, TRUE) < 0) | ||
2046 | 2746 | goto error; | ||
2047 | 2747 | |||
2048 | 2748 | if (state_modify_cloexec (process_data->job_process_fd, TRUE) < 0) | ||
2049 | 2749 | goto error; | ||
2050 | 2750 | } | ||
2051 | 2751 | |||
2052 | 2752 | return process_data; | ||
2053 | 2753 | |||
2054 | 2754 | error: | ||
2055 | 2755 | if (process_data) | ||
2056 | 2756 | nih_free (process_data); | ||
2057 | 2757 | |||
2058 | 2758 | return NULL; | ||
2059 | 2759 | } | ||
2060 | 2331 | 2760 | ||
2061 | === modified file 'init/job_process.h' | |||
2062 | --- init/job_process.h 2013-05-15 13:21:54 +0000 | |||
2063 | +++ init/job_process.h 2014-05-22 13:31:23 +0000 | |||
2064 | @@ -125,15 +125,38 @@ | |||
2065 | 125 | } JobProcessError; | 125 | } JobProcessError; |
2066 | 126 | 126 | ||
2067 | 127 | 127 | ||
2068 | 128 | /** | ||
2069 | 129 | * JobProcessErrorHandler: | ||
2070 | 130 | * | ||
2071 | 131 | * @job: job, | ||
2072 | 132 | * @state: required state job is attempting to achieve, | ||
2073 | 133 | * @process: job process that failed. | ||
2074 | 134 | * | ||
2075 | 135 | * Function that is called when a job process @process fails to start. | ||
2076 | 136 | **/ | ||
2077 | 137 | typedef void (*JobProcessErrorHandler) (Job *job, JobState state, ProcessType process); | ||
2078 | 138 | |||
2079 | 128 | NIH_BEGIN_EXTERN | 139 | NIH_BEGIN_EXTERN |
2080 | 129 | 140 | ||
2082 | 130 | int job_process_run (Job *job, ProcessType process); | 141 | void job_process_start (Job *job, ProcessType process); |
2083 | 142 | void job_process_run_bottom (JobProcessData *handler_data); | ||
2084 | 143 | |||
2085 | 144 | void job_process_child_reader (JobProcessData *handler_data, NihIo *io, | ||
2086 | 145 | const char *buf, size_t len); | ||
2087 | 146 | |||
2088 | 147 | void job_process_close_handler (JobProcessData *handler_data, NihIo *io); | ||
2089 | 131 | 148 | ||
2090 | 132 | pid_t job_process_spawn (Job *job, char * const argv[], | 149 | pid_t job_process_spawn (Job *job, char * const argv[], |
2091 | 133 | char * const *env, int trace, int script_fd, | 150 | char * const *env, int trace, int script_fd, |
2092 | 134 | ProcessType process) | 151 | ProcessType process) |
2093 | 135 | __attribute__ ((warn_unused_result)); | 152 | __attribute__ ((warn_unused_result)); |
2094 | 136 | 153 | ||
2095 | 154 | pid_t job_process_spawn_with_fd (Job *job, char * const argv[], | ||
2096 | 155 | char * const *env, int trace, int script_fd, | ||
2097 | 156 | ProcessType process, int *job_process_fd) | ||
2098 | 157 | __attribute__ ((warn_unused_result)); | ||
2099 | 158 | |||
2100 | 159 | |||
2101 | 137 | void job_process_kill (Job *job, ProcessType process); | 160 | void job_process_kill (Job *job, ProcessType process); |
2102 | 138 | 161 | ||
2103 | 139 | void job_process_handler (void *ptr, pid_t pid, | 162 | void job_process_handler (void *ptr, pid_t pid, |
2104 | @@ -145,8 +168,8 @@ | |||
2105 | 145 | __attribute__ ((warn_unused_result)); | 168 | __attribute__ ((warn_unused_result)); |
2106 | 146 | 169 | ||
2107 | 147 | void job_process_set_kill_timer (Job *job, | 170 | void job_process_set_kill_timer (Job *job, |
2110 | 148 | ProcessType process, | 171 | ProcessType process, |
2111 | 149 | time_t timeout); | 172 | time_t timeout); |
2112 | 150 | 173 | ||
2113 | 151 | void job_process_adj_kill_timer (Job *job, time_t due); | 174 | void job_process_adj_kill_timer (Job *job, time_t due); |
2114 | 152 | 175 | ||
2115 | @@ -154,6 +177,20 @@ | |||
2116 | 154 | 177 | ||
2117 | 155 | void job_process_stop_all (void); | 178 | void job_process_stop_all (void); |
2118 | 156 | 179 | ||
2119 | 180 | JobProcessData * | ||
2120 | 181 | job_process_data_new (void *parent, Job *job, ProcessType process, int job_process_fd) | ||
2121 | 182 | __attribute__ ((warn_unused_result)); | ||
2122 | 183 | |||
2123 | 184 | json_object * | ||
2124 | 185 | job_process_data_serialise (const Job *job, const JobProcessData *handler_data) | ||
2125 | 186 | __attribute__ ((warn_unused_result)); | ||
2126 | 187 | |||
2127 | 188 | JobProcessData * | ||
2128 | 189 | job_process_data_deserialise (void *parent, Job *job, json_object *json) | ||
2129 | 190 | __attribute__ ((warn_unused_result)); | ||
2130 | 191 | |||
2131 | 192 | void job_process_error_handler (const char *buf, size_t len); | ||
2132 | 193 | |||
2133 | 157 | NIH_END_EXTERN | 194 | NIH_END_EXTERN |
2134 | 158 | 195 | ||
2135 | 159 | #endif /* INIT_JOB_PROCESS_H */ | 196 | #endif /* INIT_JOB_PROCESS_H */ |
2136 | 160 | 197 | ||
2137 | === modified file 'init/log.c' | |||
2138 | --- init/log.c 2014-05-07 16:34:44 +0000 | |||
2139 | +++ init/log.c 2014-05-22 13:31:23 +0000 | |||
2140 | @@ -974,7 +974,7 @@ | |||
2141 | 974 | nih_assert (io_watch_fd != -1); | 974 | nih_assert (io_watch_fd != -1); |
2142 | 975 | 975 | ||
2143 | 976 | /* re-apply CLOEXEC flag to stop job fd being leaked to children */ | 976 | /* re-apply CLOEXEC flag to stop job fd being leaked to children */ |
2145 | 977 | if (state_toggle_cloexec (io_watch_fd, TRUE) < 0) | 977 | if (state_modify_cloexec (io_watch_fd, TRUE) < 0) |
2146 | 978 | return NULL; | 978 | return NULL; |
2147 | 979 | 979 | ||
2148 | 980 | if (! state_get_json_int_var (json, "uid", uid)) | 980 | if (! state_get_json_int_var (json, "uid", uid)) |
2149 | @@ -993,7 +993,7 @@ | |||
2150 | 993 | * we would never close the fd. | 993 | * we would never close the fd. |
2151 | 994 | */ | 994 | */ |
2152 | 995 | if (log->fd != -1) | 995 | if (log->fd != -1) |
2154 | 996 | (void)state_toggle_cloexec (log->fd, TRUE); | 996 | (void)state_modify_cloexec (log->fd, TRUE); |
2155 | 997 | 997 | ||
2156 | 998 | log->unflushed = nih_io_buffer_new (log); | 998 | log->unflushed = nih_io_buffer_new (log); |
2157 | 999 | if (! log->unflushed) | 999 | if (! log->unflushed) |
2158 | 1000 | 1000 | ||
2159 | === modified file 'init/state.c' | |||
2160 | --- init/state.c 2014-05-07 16:34:44 +0000 | |||
2161 | +++ init/state.c 2014-05-22 13:31:23 +0000 | |||
2162 | @@ -532,7 +532,7 @@ | |||
2163 | 532 | 532 | ||
2164 | 533 | 533 | ||
2165 | 534 | /** | 534 | /** |
2167 | 535 | * state_toggle_cloexec: | 535 | * state_modify_cloexec: |
2168 | 536 | * | 536 | * |
2169 | 537 | * @fd: file descriptor, | 537 | * @fd: file descriptor, |
2170 | 538 | * @set: set close-on-exec flag if TRUE, clear if FALSE. | 538 | * @set: set close-on-exec flag if TRUE, clear if FALSE. |
2171 | @@ -542,7 +542,7 @@ | |||
2172 | 542 | * Returns: 0 on success, -1 on error. | 542 | * Returns: 0 on success, -1 on error. |
2173 | 543 | **/ | 543 | **/ |
2174 | 544 | int | 544 | int |
2176 | 545 | state_toggle_cloexec (int fd, int set) | 545 | state_modify_cloexec (int fd, int set) |
2177 | 546 | { | 546 | { |
2178 | 547 | long flags; | 547 | long flags; |
2179 | 548 | int ret; | 548 | int ret; |
2180 | 549 | 549 | ||
2181 | === modified file 'init/state.h' | |||
2182 | --- init/state.h 2013-06-04 16:51:55 +0000 | |||
2183 | +++ init/state.h 2014-05-22 13:31:23 +0000 | |||
2184 | @@ -1144,7 +1144,7 @@ | |||
2185 | 1144 | int state_from_string (const char *state) | 1144 | int state_from_string (const char *state) |
2186 | 1145 | __attribute__ ((warn_unused_result)); | 1145 | __attribute__ ((warn_unused_result)); |
2187 | 1146 | 1146 | ||
2189 | 1147 | int state_toggle_cloexec (int fd, int set); | 1147 | int state_modify_cloexec (int fd, int set); |
2190 | 1148 | 1148 | ||
2191 | 1149 | json_object * | 1149 | json_object * |
2192 | 1150 | state_serialise_str_array (char ** const array) | 1150 | state_serialise_str_array (char ** const array) |
2193 | 1151 | 1151 | ||
2194 | === modified file 'init/tests/test_event.c' | |||
2195 | --- init/tests/test_event.c 2013-01-31 17:23:55 +0000 | |||
2196 | +++ init/tests/test_event.c 2014-05-22 13:31:23 +0000 | |||
2197 | @@ -300,7 +300,7 @@ | |||
2198 | 300 | job = (Job *)nih_hash_lookup (class->instances, ""); | 300 | job = (Job *)nih_hash_lookup (class->instances, ""); |
2199 | 301 | 301 | ||
2200 | 302 | TEST_EQ (job->goal, JOB_START); | 302 | TEST_EQ (job->goal, JOB_START); |
2202 | 303 | TEST_EQ (job->state, JOB_RUNNING); | 303 | TEST_EQ (job->state, JOB_SPAWNED); |
2203 | 304 | TEST_GT (job->pid[PROCESS_MAIN], 0); | 304 | TEST_GT (job->pid[PROCESS_MAIN], 0); |
2204 | 305 | 305 | ||
2205 | 306 | waitpid (job->pid[PROCESS_MAIN], NULL, 0); | 306 | waitpid (job->pid[PROCESS_MAIN], NULL, 0); |
2206 | @@ -1739,7 +1739,7 @@ | |||
2207 | 1739 | job = (Job *)nih_hash_lookup (class->instances, ""); | 1739 | job = (Job *)nih_hash_lookup (class->instances, ""); |
2208 | 1740 | 1740 | ||
2209 | 1741 | TEST_EQ (job->goal, JOB_START); | 1741 | TEST_EQ (job->goal, JOB_START); |
2211 | 1742 | TEST_EQ (job->state, JOB_RUNNING); | 1742 | TEST_EQ (job->state, JOB_SPAWNED); |
2212 | 1743 | TEST_GT (job->pid[PROCESS_MAIN], 0); | 1743 | TEST_GT (job->pid[PROCESS_MAIN], 0); |
2213 | 1744 | 1744 | ||
2214 | 1745 | waitpid (job->pid[PROCESS_MAIN], NULL, 0); | 1745 | waitpid (job->pid[PROCESS_MAIN], NULL, 0); |
2215 | 1746 | 1746 | ||
2216 | === modified file 'init/tests/test_job.c' | |||
2217 | --- init/tests/test_job.c 2013-11-18 16:38:32 +0000 | |||
2218 | +++ init/tests/test_job.c 2014-05-22 13:31:23 +0000 | |||
2219 | @@ -60,7 +60,15 @@ | |||
2220 | 60 | #include "conf.h" | 60 | #include "conf.h" |
2221 | 61 | #include "control.h" | 61 | #include "control.h" |
2222 | 62 | #include "state.h" | 62 | #include "state.h" |
2223 | 63 | #include "test_util_common.h" | ||
2224 | 63 | 64 | ||
2225 | 65 | void | ||
2226 | 66 | job_quit_with_state (void *data, NihMainLoopFunc *loop) | ||
2227 | 67 | { | ||
2228 | 68 | Job *job; | ||
2229 | 69 | job = (Job *)data; | ||
2230 | 70 | nih_main_loop_exit (job->state); | ||
2231 | 71 | } | ||
2232 | 64 | 72 | ||
2233 | 65 | char *argv0; | 73 | char *argv0; |
2234 | 66 | 74 | ||
2235 | @@ -165,6 +173,12 @@ | |||
2236 | 165 | TEST_EQ_P (job->log[i], NULL); | 173 | TEST_EQ_P (job->log[i], NULL); |
2237 | 166 | } | 174 | } |
2238 | 167 | 175 | ||
2239 | 176 | TEST_NE_P (job->process_data, NULL); | ||
2240 | 177 | TEST_ALLOC_SIZE (job->log, sizeof (JobProcessData *) * PROCESS_LAST); | ||
2241 | 178 | for (i = 0; i < PROCESS_LAST; i++) { | ||
2242 | 179 | TEST_EQ_P (job->process_data[i], NULL); | ||
2243 | 180 | } | ||
2244 | 181 | |||
2245 | 168 | event_operator_reset (job->stop_on); | 182 | event_operator_reset (job->stop_on); |
2246 | 169 | 183 | ||
2247 | 170 | nih_free (job); | 184 | nih_free (job); |
2248 | @@ -701,6 +715,10 @@ | |||
2249 | 701 | char *path, *job_path = NULL, *state; | 715 | char *path, *job_path = NULL, *state; |
2250 | 702 | int status; | 716 | int status; |
2251 | 703 | 717 | ||
2252 | 718 | nih_error_init (); | ||
2253 | 719 | nih_main_loop_init (); | ||
2254 | 720 | event_init (); | ||
2255 | 721 | |||
2256 | 704 | TEST_FUNCTION ("job_change_state"); | 722 | TEST_FUNCTION ("job_change_state"); |
2257 | 705 | program_name = "test"; | 723 | program_name = "test"; |
2258 | 706 | output = tmpfile (); | 724 | output = tmpfile (); |
2259 | @@ -1059,7 +1077,7 @@ | |||
2260 | 1059 | job->failed_process = PROCESS_INVALID; | 1077 | job->failed_process = PROCESS_INVALID; |
2261 | 1060 | job->exit_status = 0; | 1078 | job->exit_status = 0; |
2262 | 1061 | 1079 | ||
2264 | 1062 | job_change_state (job, JOB_PRE_START); | 1080 | job_change_state (job, JOB_PRE_STARTING); |
2265 | 1063 | 1081 | ||
2266 | 1064 | TEST_EQ (job->goal, JOB_START); | 1082 | TEST_EQ (job->goal, JOB_START); |
2267 | 1065 | TEST_EQ (job->state, JOB_PRE_START); | 1083 | TEST_EQ (job->state, JOB_PRE_START); |
2268 | @@ -1110,6 +1128,7 @@ | |||
2269 | 1110 | blocked = blocked_new (job, BLOCKED_EVENT, cause); | 1128 | blocked = blocked_new (job, BLOCKED_EVENT, cause); |
2270 | 1111 | event_block (cause); | 1129 | event_block (cause); |
2271 | 1112 | nih_list_add (&job->blocking, &blocked->entry); | 1130 | nih_list_add (&job->blocking, &blocked->entry); |
2272 | 1131 | TEST_NE_P (nih_main_loop_add_func (job, job_quit_with_state, job), NULL); | ||
2273 | 1113 | } | 1132 | } |
2274 | 1114 | 1133 | ||
2275 | 1115 | job->goal = JOB_START; | 1134 | job->goal = JOB_START; |
2276 | @@ -1125,7 +1144,8 @@ | |||
2277 | 1125 | job->failed_process = PROCESS_INVALID; | 1144 | job->failed_process = PROCESS_INVALID; |
2278 | 1126 | job->exit_status = 0; | 1145 | job->exit_status = 0; |
2279 | 1127 | 1146 | ||
2281 | 1128 | job_change_state (job, JOB_PRE_START); | 1147 | job_change_state (job, JOB_PRE_STARTING); |
2282 | 1148 | while (nih_main_loop () < JOB_RUNNING) {} | ||
2283 | 1129 | 1149 | ||
2284 | 1130 | TEST_EQ (job->goal, JOB_START); | 1150 | TEST_EQ (job->goal, JOB_START); |
2285 | 1131 | TEST_EQ (job->state, JOB_RUNNING); | 1151 | TEST_EQ (job->state, JOB_RUNNING); |
2286 | @@ -1184,6 +1204,7 @@ | |||
2287 | 1184 | blocked = blocked_new (job, BLOCKED_EVENT, cause); | 1204 | blocked = blocked_new (job, BLOCKED_EVENT, cause); |
2288 | 1185 | event_block (cause); | 1205 | event_block (cause); |
2289 | 1186 | nih_list_add (&job->blocking, &blocked->entry); | 1206 | nih_list_add (&job->blocking, &blocked->entry); |
2290 | 1207 | TEST_NE_P (nih_main_loop_add_func (job, job_quit_with_state, job), NULL); | ||
2291 | 1187 | } | 1208 | } |
2292 | 1188 | 1209 | ||
2293 | 1189 | job->goal = JOB_START; | 1210 | job->goal = JOB_START; |
2294 | @@ -1200,12 +1221,14 @@ | |||
2295 | 1200 | job->exit_status = 0; | 1221 | job->exit_status = 0; |
2296 | 1201 | 1222 | ||
2297 | 1202 | TEST_DIVERT_STDERR (output) { | 1223 | TEST_DIVERT_STDERR (output) { |
2299 | 1203 | job_change_state (job, JOB_PRE_START); | 1224 | job_change_state (job, JOB_PRE_STARTING); |
2300 | 1225 | while (nih_main_loop() < JOB_STOPPING) {} | ||
2301 | 1204 | } | 1226 | } |
2302 | 1205 | rewind (output); | 1227 | rewind (output); |
2303 | 1206 | 1228 | ||
2304 | 1207 | TEST_EQ (job->goal, JOB_STOP); | 1229 | TEST_EQ (job->goal, JOB_STOP); |
2305 | 1208 | TEST_EQ (job->state, JOB_STOPPING); | 1230 | TEST_EQ (job->state, JOB_STOPPING); |
2306 | 1231 | TEST_FALSE (job->process_data[PROCESS_PRE_START]->valid); | ||
2307 | 1209 | TEST_EQ (job->pid[PROCESS_PRE_START], 0); | 1232 | TEST_EQ (job->pid[PROCESS_PRE_START], 0); |
2308 | 1210 | 1233 | ||
2309 | 1211 | TEST_EQ (cause->blockers, 0); | 1234 | TEST_EQ (cause->blockers, 0); |
2310 | @@ -1269,6 +1292,7 @@ | |||
2311 | 1269 | blocked = blocked_new (job, BLOCKED_EVENT, cause); | 1292 | blocked = blocked_new (job, BLOCKED_EVENT, cause); |
2312 | 1270 | event_block (cause); | 1293 | event_block (cause); |
2313 | 1271 | nih_list_add (&job->blocking, &blocked->entry); | 1294 | nih_list_add (&job->blocking, &blocked->entry); |
2314 | 1295 | TEST_NE_P (nih_main_loop_add_func (job, job_quit_with_state, job), NULL); | ||
2315 | 1272 | } | 1296 | } |
2316 | 1273 | 1297 | ||
2317 | 1274 | job->goal = JOB_START; | 1298 | job->goal = JOB_START; |
2318 | @@ -1284,7 +1308,8 @@ | |||
2319 | 1284 | job->failed_process = PROCESS_INVALID; | 1308 | job->failed_process = PROCESS_INVALID; |
2320 | 1285 | job->exit_status = 0; | 1309 | job->exit_status = 0; |
2321 | 1286 | 1310 | ||
2323 | 1287 | job_change_state (job, JOB_SPAWNED); | 1311 | job_change_state (job, JOB_SPAWNING); |
2324 | 1312 | while (nih_main_loop() < JOB_RUNNING) {} | ||
2325 | 1288 | 1313 | ||
2326 | 1289 | TEST_EQ (job->goal, JOB_START); | 1314 | TEST_EQ (job->goal, JOB_START); |
2327 | 1290 | TEST_EQ (job->state, JOB_RUNNING); | 1315 | TEST_EQ (job->state, JOB_RUNNING); |
2328 | @@ -1337,6 +1362,7 @@ | |||
2329 | 1337 | blocked = blocked_new (job, BLOCKED_EVENT, cause); | 1362 | blocked = blocked_new (job, BLOCKED_EVENT, cause); |
2330 | 1338 | event_block (cause); | 1363 | event_block (cause); |
2331 | 1339 | nih_list_add (&job->blocking, &blocked->entry); | 1364 | nih_list_add (&job->blocking, &blocked->entry); |
2332 | 1365 | TEST_NE_P (nih_main_loop_add_func (job, job_quit_with_state, job), NULL); | ||
2333 | 1340 | } | 1366 | } |
2334 | 1341 | 1367 | ||
2335 | 1342 | job->goal = JOB_START; | 1368 | job->goal = JOB_START; |
2336 | @@ -1352,7 +1378,8 @@ | |||
2337 | 1352 | job->failed_process = PROCESS_INVALID; | 1378 | job->failed_process = PROCESS_INVALID; |
2338 | 1353 | job->exit_status = 0; | 1379 | job->exit_status = 0; |
2339 | 1354 | 1380 | ||
2341 | 1355 | job_change_state (job, JOB_SPAWNED); | 1381 | job_change_state (job, JOB_SPAWNING); |
2342 | 1382 | while (nih_main_loop() < JOB_RUNNING) {} | ||
2343 | 1356 | 1383 | ||
2344 | 1357 | TEST_EQ (job->goal, JOB_START); | 1384 | TEST_EQ (job->goal, JOB_START); |
2345 | 1358 | TEST_EQ (job->state, JOB_RUNNING); | 1385 | TEST_EQ (job->state, JOB_RUNNING); |
2346 | @@ -1417,6 +1444,7 @@ | |||
2347 | 1417 | blocked = blocked_new (job, BLOCKED_EVENT, cause); | 1444 | blocked = blocked_new (job, BLOCKED_EVENT, cause); |
2348 | 1418 | event_block (cause); | 1445 | event_block (cause); |
2349 | 1419 | nih_list_add (&job->blocking, &blocked->entry); | 1446 | nih_list_add (&job->blocking, &blocked->entry); |
2350 | 1447 | TEST_NE_P (nih_main_loop_add_func (job, job_quit_with_state, job), NULL); | ||
2351 | 1420 | } | 1448 | } |
2352 | 1421 | 1449 | ||
2353 | 1422 | job->goal = JOB_START; | 1450 | job->goal = JOB_START; |
2354 | @@ -1432,7 +1460,8 @@ | |||
2355 | 1432 | job->failed_process = PROCESS_INVALID; | 1460 | job->failed_process = PROCESS_INVALID; |
2356 | 1433 | job->exit_status = 0; | 1461 | job->exit_status = 0; |
2357 | 1434 | 1462 | ||
2359 | 1435 | job_change_state (job, JOB_SPAWNED); | 1463 | job_change_state (job, JOB_SPAWNING); |
2360 | 1464 | while (nih_main_loop() < JOB_RUNNING) {} | ||
2361 | 1436 | 1465 | ||
2362 | 1437 | TEST_EQ (job->goal, JOB_START); | 1466 | TEST_EQ (job->goal, JOB_START); |
2363 | 1438 | TEST_EQ (job->state, JOB_RUNNING); | 1467 | TEST_EQ (job->state, JOB_RUNNING); |
2364 | @@ -1507,7 +1536,7 @@ | |||
2365 | 1507 | job->failed_process = PROCESS_INVALID; | 1536 | job->failed_process = PROCESS_INVALID; |
2366 | 1508 | job->exit_status = 0; | 1537 | job->exit_status = 0; |
2367 | 1509 | 1538 | ||
2369 | 1510 | job_change_state (job, JOB_SPAWNED); | 1539 | job_change_state (job, JOB_SPAWNING); |
2370 | 1511 | 1540 | ||
2371 | 1512 | TEST_EQ (job->goal, JOB_START); | 1541 | TEST_EQ (job->goal, JOB_START); |
2372 | 1513 | TEST_EQ (job->state, JOB_RUNNING); | 1542 | TEST_EQ (job->state, JOB_RUNNING); |
2373 | @@ -1556,6 +1585,7 @@ | |||
2374 | 1556 | blocked = blocked_new (job, BLOCKED_EVENT, cause); | 1585 | blocked = blocked_new (job, BLOCKED_EVENT, cause); |
2375 | 1557 | event_block (cause); | 1586 | event_block (cause); |
2376 | 1558 | nih_list_add (&job->blocking, &blocked->entry); | 1587 | nih_list_add (&job->blocking, &blocked->entry); |
2377 | 1588 | TEST_NE_P (nih_main_loop_add_func (job, job_quit_with_state, job), NULL); | ||
2378 | 1559 | } | 1589 | } |
2379 | 1560 | 1590 | ||
2380 | 1561 | job->goal = JOB_START; | 1591 | job->goal = JOB_START; |
2381 | @@ -1572,12 +1602,14 @@ | |||
2382 | 1572 | job->exit_status = 0; | 1602 | job->exit_status = 0; |
2383 | 1573 | 1603 | ||
2384 | 1574 | TEST_DIVERT_STDERR (output) { | 1604 | TEST_DIVERT_STDERR (output) { |
2386 | 1575 | job_change_state (job, JOB_SPAWNED); | 1605 | job_change_state (job, JOB_SPAWNING); |
2387 | 1606 | while (nih_main_loop() < JOB_STOPPING) {} | ||
2388 | 1576 | } | 1607 | } |
2389 | 1577 | rewind (output); | 1608 | rewind (output); |
2390 | 1578 | 1609 | ||
2391 | 1579 | TEST_EQ (job->goal, JOB_STOP); | 1610 | TEST_EQ (job->goal, JOB_STOP); |
2392 | 1580 | TEST_EQ (job->state, JOB_STOPPING); | 1611 | TEST_EQ (job->state, JOB_STOPPING); |
2393 | 1612 | TEST_FALSE (job->process_data[PROCESS_MAIN]->valid); | ||
2394 | 1581 | TEST_EQ (job->pid[PROCESS_MAIN], 0); | 1613 | TEST_EQ (job->pid[PROCESS_MAIN], 0); |
2395 | 1582 | 1614 | ||
2396 | 1583 | TEST_EQ (cause->blockers, 0); | 1615 | TEST_EQ (cause->blockers, 0); |
2397 | @@ -1658,7 +1690,7 @@ | |||
2398 | 1658 | job->failed_process = PROCESS_INVALID; | 1690 | job->failed_process = PROCESS_INVALID; |
2399 | 1659 | job->exit_status = 0; | 1691 | job->exit_status = 0; |
2400 | 1660 | 1692 | ||
2402 | 1661 | job_change_state (job, JOB_SPAWNED); | 1693 | job_change_state (job, JOB_SPAWNING); |
2403 | 1662 | 1694 | ||
2404 | 1663 | TEST_EQ (job->goal, JOB_START); | 1695 | TEST_EQ (job->goal, JOB_START); |
2405 | 1664 | TEST_EQ (job->state, JOB_SPAWNED); | 1696 | TEST_EQ (job->state, JOB_SPAWNED); |
2406 | @@ -1727,7 +1759,7 @@ | |||
2407 | 1727 | job->failed_process = PROCESS_INVALID; | 1759 | job->failed_process = PROCESS_INVALID; |
2408 | 1728 | job->exit_status = 0; | 1760 | job->exit_status = 0; |
2409 | 1729 | 1761 | ||
2411 | 1730 | job_change_state (job, JOB_POST_START); | 1762 | job_change_state (job, JOB_POST_STARTING); |
2412 | 1731 | 1763 | ||
2413 | 1732 | TEST_EQ (job->goal, JOB_START); | 1764 | TEST_EQ (job->goal, JOB_START); |
2414 | 1733 | TEST_EQ (job->state, JOB_POST_START); | 1765 | TEST_EQ (job->state, JOB_POST_START); |
2415 | @@ -1794,7 +1826,7 @@ | |||
2416 | 1794 | job->failed_process = PROCESS_INVALID; | 1826 | job->failed_process = PROCESS_INVALID; |
2417 | 1795 | job->exit_status = 0; | 1827 | job->exit_status = 0; |
2418 | 1796 | 1828 | ||
2420 | 1797 | job_change_state (job, JOB_POST_START); | 1829 | job_change_state (job, JOB_POST_STARTING); |
2421 | 1798 | 1830 | ||
2422 | 1799 | TEST_EQ (job->goal, JOB_START); | 1831 | TEST_EQ (job->goal, JOB_START); |
2423 | 1800 | TEST_EQ (job->state, JOB_RUNNING); | 1832 | TEST_EQ (job->state, JOB_RUNNING); |
2424 | @@ -1842,6 +1874,7 @@ | |||
2425 | 1842 | blocked = blocked_new (job, BLOCKED_EVENT, cause); | 1874 | blocked = blocked_new (job, BLOCKED_EVENT, cause); |
2426 | 1843 | event_block (cause); | 1875 | event_block (cause); |
2427 | 1844 | nih_list_add (&job->blocking, &blocked->entry); | 1876 | nih_list_add (&job->blocking, &blocked->entry); |
2428 | 1877 | TEST_NE_P (nih_main_loop_add_func (job, job_quit_with_state, job), NULL); | ||
2429 | 1845 | } | 1878 | } |
2430 | 1846 | 1879 | ||
2431 | 1847 | job->goal = JOB_START; | 1880 | job->goal = JOB_START; |
2432 | @@ -1858,7 +1891,8 @@ | |||
2433 | 1858 | job->exit_status = 0; | 1891 | job->exit_status = 0; |
2434 | 1859 | 1892 | ||
2435 | 1860 | TEST_DIVERT_STDERR (output) { | 1893 | TEST_DIVERT_STDERR (output) { |
2437 | 1861 | job_change_state (job, JOB_POST_START); | 1894 | job_change_state (job, JOB_POST_STARTING); |
2438 | 1895 | while (nih_main_loop () < JOB_RUNNING) { } | ||
2439 | 1862 | } | 1896 | } |
2440 | 1863 | rewind (output); | 1897 | rewind (output); |
2441 | 1864 | 1898 | ||
2442 | @@ -2058,7 +2092,7 @@ | |||
2443 | 2058 | job->failed_process = PROCESS_INVALID; | 2092 | job->failed_process = PROCESS_INVALID; |
2444 | 2059 | job->exit_status = 0; | 2093 | job->exit_status = 0; |
2445 | 2060 | 2094 | ||
2447 | 2061 | job_change_state (job, JOB_PRE_STOP); | 2095 | job_change_state (job, JOB_PRE_STOPPING); |
2448 | 2062 | 2096 | ||
2449 | 2063 | TEST_EQ (job->goal, JOB_STOP); | 2097 | TEST_EQ (job->goal, JOB_STOP); |
2450 | 2064 | TEST_EQ (job->state, JOB_PRE_STOP); | 2098 | TEST_EQ (job->state, JOB_PRE_STOP); |
2451 | @@ -2125,7 +2159,7 @@ | |||
2452 | 2125 | job->failed_process = PROCESS_INVALID; | 2159 | job->failed_process = PROCESS_INVALID; |
2453 | 2126 | job->exit_status = 0; | 2160 | job->exit_status = 0; |
2454 | 2127 | 2161 | ||
2456 | 2128 | job_change_state (job, JOB_PRE_STOP); | 2162 | job_change_state (job, JOB_PRE_STOPPING); |
2457 | 2129 | 2163 | ||
2458 | 2130 | TEST_EQ (job->goal, JOB_STOP); | 2164 | TEST_EQ (job->goal, JOB_STOP); |
2459 | 2131 | TEST_EQ (job->state, JOB_STOPPING); | 2165 | TEST_EQ (job->state, JOB_STOPPING); |
2460 | @@ -2198,7 +2232,7 @@ | |||
2461 | 2198 | job->failed_process = PROCESS_INVALID; | 2232 | job->failed_process = PROCESS_INVALID; |
2462 | 2199 | job->exit_status = 0; | 2233 | job->exit_status = 0; |
2463 | 2200 | 2234 | ||
2465 | 2201 | job_change_state (job, JOB_PRE_STOP); | 2235 | job_change_state (job, JOB_PRE_STOPPING); |
2466 | 2202 | 2236 | ||
2467 | 2203 | TEST_EQ (job->goal, JOB_STOP); | 2237 | TEST_EQ (job->goal, JOB_STOP); |
2468 | 2204 | TEST_EQ (job->state, JOB_STOPPING); | 2238 | TEST_EQ (job->state, JOB_STOPPING); |
2469 | @@ -2283,7 +2317,7 @@ | |||
2470 | 2283 | job->failed_process = PROCESS_INVALID; | 2317 | job->failed_process = PROCESS_INVALID; |
2471 | 2284 | job->exit_status = 0; | 2318 | job->exit_status = 0; |
2472 | 2285 | 2319 | ||
2474 | 2286 | job_change_state (job, JOB_PRE_STOP); | 2320 | job_change_state (job, JOB_PRE_STOPPING); |
2475 | 2287 | 2321 | ||
2476 | 2288 | TEST_EQ (job->goal, JOB_STOP); | 2322 | TEST_EQ (job->goal, JOB_STOP); |
2477 | 2289 | TEST_EQ (job->state, JOB_STOPPING); | 2323 | TEST_EQ (job->state, JOB_STOPPING); |
2478 | @@ -2348,6 +2382,7 @@ | |||
2479 | 2348 | blocked = blocked_new (job, BLOCKED_EVENT, cause); | 2382 | blocked = blocked_new (job, BLOCKED_EVENT, cause); |
2480 | 2349 | event_block (cause); | 2383 | event_block (cause); |
2481 | 2350 | nih_list_add (&job->blocking, &blocked->entry); | 2384 | nih_list_add (&job->blocking, &blocked->entry); |
2482 | 2385 | TEST_NE_P (nih_main_loop_add_func (job, job_quit_with_state, job), NULL); | ||
2483 | 2351 | } | 2386 | } |
2484 | 2352 | 2387 | ||
2485 | 2353 | job->goal = JOB_STOP; | 2388 | job->goal = JOB_STOP; |
2486 | @@ -2364,7 +2399,8 @@ | |||
2487 | 2364 | job->exit_status = 0; | 2399 | job->exit_status = 0; |
2488 | 2365 | 2400 | ||
2489 | 2366 | TEST_DIVERT_STDERR (output) { | 2401 | TEST_DIVERT_STDERR (output) { |
2491 | 2367 | job_change_state (job, JOB_PRE_STOP); | 2402 | job_change_state (job, JOB_PRE_STOPPING); |
2492 | 2403 | while (nih_main_loop () < JOB_STOPPING) {} | ||
2493 | 2368 | } | 2404 | } |
2494 | 2369 | rewind (output); | 2405 | rewind (output); |
2495 | 2370 | 2406 | ||
2496 | @@ -3100,7 +3136,7 @@ | |||
2497 | 3100 | job->failed_process = PROCESS_INVALID; | 3136 | job->failed_process = PROCESS_INVALID; |
2498 | 3101 | job->exit_status = 0; | 3137 | job->exit_status = 0; |
2499 | 3102 | 3138 | ||
2501 | 3103 | job_change_state (job, JOB_POST_STOP); | 3139 | job_change_state (job, JOB_POST_STOPPING); |
2502 | 3104 | 3140 | ||
2503 | 3105 | TEST_EQ (job->goal, JOB_STOP); | 3141 | TEST_EQ (job->goal, JOB_STOP); |
2504 | 3106 | TEST_EQ (job->state, JOB_POST_STOP); | 3142 | TEST_EQ (job->state, JOB_POST_STOP); |
2505 | @@ -3168,7 +3204,7 @@ | |||
2506 | 3168 | 3204 | ||
2507 | 3169 | TEST_FREE_TAG (job); | 3205 | TEST_FREE_TAG (job); |
2508 | 3170 | 3206 | ||
2510 | 3171 | job_change_state (job, JOB_POST_STOP); | 3207 | job_change_state (job, JOB_POST_STOPPING); |
2511 | 3172 | 3208 | ||
2512 | 3173 | TEST_FREE (job); | 3209 | TEST_FREE (job); |
2513 | 3174 | 3210 | ||
2514 | @@ -3228,7 +3264,8 @@ | |||
2515 | 3228 | TEST_FREE_TAG (job); | 3264 | TEST_FREE_TAG (job); |
2516 | 3229 | 3265 | ||
2517 | 3230 | TEST_DIVERT_STDERR (output) { | 3266 | TEST_DIVERT_STDERR (output) { |
2519 | 3231 | job_change_state (job, JOB_POST_STOP); | 3267 | job_change_state (job, JOB_POST_STOPPING); |
2520 | 3268 | TEST_WATCH_LOOP (); | ||
2521 | 3232 | } | 3269 | } |
2522 | 3233 | rewind (output); | 3270 | rewind (output); |
2523 | 3234 | 3271 | ||
2524 | @@ -4000,22 +4037,31 @@ | |||
2525 | 4000 | 4037 | ||
2526 | 4001 | 4038 | ||
2527 | 4002 | /* Check that the next state if we're starting a starting job is | 4039 | /* Check that the next state if we're starting a starting job is |
2528 | 4040 | * sec-spawning. | ||
2529 | 4041 | */ | ||
2530 | 4042 | TEST_FEATURE ("with starting job and a goal of start"); | ||
2531 | 4043 | job->goal = JOB_START; | ||
2532 | 4044 | job->state = JOB_STARTING; | ||
2533 | 4045 | |||
2534 | 4046 | TEST_EQ (job_next_state (job), JOB_SECURITY_SPAWNING); | ||
2535 | 4047 | |||
2536 | 4048 | /* Check that the next state if we're starting a sec-spawning job is | ||
2537 | 4003 | * security. | 4049 | * security. |
2538 | 4004 | */ | 4050 | */ |
2539 | 4005 | TEST_FEATURE ("with starting job and a goal of start"); | 4051 | TEST_FEATURE ("with starting job and a goal of start"); |
2540 | 4006 | job->goal = JOB_START; | 4052 | job->goal = JOB_START; |
2542 | 4007 | job->state = JOB_STARTING; | 4053 | job->state = JOB_SECURITY_SPAWNING; |
2543 | 4008 | 4054 | ||
2544 | 4009 | TEST_EQ (job_next_state (job), JOB_SECURITY); | 4055 | TEST_EQ (job_next_state (job), JOB_SECURITY); |
2545 | 4010 | 4056 | ||
2546 | 4011 | /* Check that the next state if we're starting a security job is | 4057 | /* Check that the next state if we're starting a security job is |
2548 | 4012 | * pre-start. | 4058 | * pre-starting. |
2549 | 4013 | */ | 4059 | */ |
2550 | 4014 | TEST_FEATURE ("with security job and a goal of start"); | 4060 | TEST_FEATURE ("with security job and a goal of start"); |
2551 | 4015 | job->goal = JOB_START; | 4061 | job->goal = JOB_START; |
2552 | 4016 | job->state = JOB_SECURITY; | 4062 | job->state = JOB_SECURITY; |
2553 | 4017 | 4063 | ||
2555 | 4018 | TEST_EQ (job_next_state (job), JOB_PRE_START); | 4064 | TEST_EQ (job_next_state (job), JOB_PRE_STARTING); |
2556 | 4019 | 4065 | ||
2557 | 4020 | /* Check that the next state if we're stopping an security job is | 4066 | /* Check that the next state if we're stopping an security job is |
2558 | 4021 | * stopping. | 4067 | * stopping. |
2559 | @@ -4026,6 +4072,25 @@ | |||
2560 | 4026 | 4072 | ||
2561 | 4027 | TEST_EQ (job_next_state (job), JOB_STOPPING); | 4073 | TEST_EQ (job_next_state (job), JOB_STOPPING); |
2562 | 4028 | 4074 | ||
2563 | 4075 | /* Check that the next state if we're starting a pre-starting job is | ||
2564 | 4076 | * pre-start. | ||
2565 | 4077 | */ | ||
2566 | 4078 | TEST_FEATURE ("with pre-stating job and a goal of start"); | ||
2567 | 4079 | job->goal = JOB_START; | ||
2568 | 4080 | job->state = JOB_PRE_STARTING; | ||
2569 | 4081 | |||
2570 | 4082 | TEST_EQ (job_next_state (job), JOB_PRE_START); | ||
2571 | 4083 | |||
2572 | 4084 | /* Check that the next state if we're stopping a pre-starting job is | ||
2573 | 4085 | * stopping. | ||
2574 | 4086 | */ | ||
2575 | 4087 | TEST_FEATURE ("with pre-starting job and a goal of stop"); | ||
2576 | 4088 | job->goal = JOB_STOP; | ||
2577 | 4089 | job->state = JOB_PRE_STARTING; | ||
2578 | 4090 | |||
2579 | 4091 | TEST_EQ (job_next_state (job), JOB_STOPPING); | ||
2580 | 4092 | |||
2581 | 4093 | |||
2582 | 4029 | /* Check that the next state if we're stopping a pre-start job is | 4094 | /* Check that the next state if we're stopping a pre-start job is |
2583 | 4030 | * stopping. | 4095 | * stopping. |
2584 | 4031 | */ | 4096 | */ |
2585 | @@ -4043,6 +4108,15 @@ | |||
2586 | 4043 | job->goal = JOB_START; | 4108 | job->goal = JOB_START; |
2587 | 4044 | job->state = JOB_PRE_START; | 4109 | job->state = JOB_PRE_START; |
2588 | 4045 | 4110 | ||
2589 | 4111 | TEST_EQ (job_next_state (job), JOB_SPAWNING); | ||
2590 | 4112 | |||
2591 | 4113 | /* Check that the next state if we're starting a spawning job is | ||
2592 | 4114 | * spawned. | ||
2593 | 4115 | */ | ||
2594 | 4116 | TEST_FEATURE ("with pre-start job and a goal of start"); | ||
2595 | 4117 | job->goal = JOB_START; | ||
2596 | 4118 | job->state = JOB_SPAWNING; | ||
2597 | 4119 | |||
2598 | 4046 | TEST_EQ (job_next_state (job), JOB_SPAWNED); | 4120 | TEST_EQ (job_next_state (job), JOB_SPAWNED); |
2599 | 4047 | 4121 | ||
2600 | 4048 | 4122 | ||
2601 | @@ -4057,11 +4131,21 @@ | |||
2602 | 4057 | 4131 | ||
2603 | 4058 | 4132 | ||
2604 | 4059 | /* Check that the next state if we're starting a spawned job is | 4133 | /* Check that the next state if we're starting a spawned job is |
2605 | 4134 | * post-starting. | ||
2606 | 4135 | */ | ||
2607 | 4136 | TEST_FEATURE ("with spawned job and a goal of start"); | ||
2608 | 4137 | job->goal = JOB_START; | ||
2609 | 4138 | job->state = JOB_SPAWNED; | ||
2610 | 4139 | |||
2611 | 4140 | TEST_EQ (job_next_state (job), JOB_POST_STARTING); | ||
2612 | 4141 | |||
2613 | 4142 | |||
2614 | 4143 | /* Check that the next state if we're starting a post-staring job is | ||
2615 | 4060 | * post-start. | 4144 | * post-start. |
2616 | 4061 | */ | 4145 | */ |
2618 | 4062 | TEST_FEATURE ("with spawned job and a goal of start"); | 4146 | TEST_FEATURE ("with post-starting job and a goal of start"); |
2619 | 4063 | job->goal = JOB_START; | 4147 | job->goal = JOB_START; |
2621 | 4064 | job->state = JOB_SPAWNED; | 4148 | job->state = JOB_POST_STARTING; |
2622 | 4065 | 4149 | ||
2623 | 4066 | TEST_EQ (job_next_state (job), JOB_POST_START); | 4150 | TEST_EQ (job_next_state (job), JOB_POST_START); |
2624 | 4067 | 4151 | ||
2625 | @@ -4106,6 +4190,17 @@ | |||
2626 | 4106 | job->state = JOB_RUNNING; | 4190 | job->state = JOB_RUNNING; |
2627 | 4107 | job->pid[PROCESS_MAIN] = 1; | 4191 | job->pid[PROCESS_MAIN] = 1; |
2628 | 4108 | 4192 | ||
2629 | 4193 | TEST_EQ (job_next_state (job), JOB_PRE_STOPPING); | ||
2630 | 4194 | |||
2631 | 4195 | /* Check that the next state if we're stopping a job with pre-stop is | ||
2632 | 4196 | * pre-stop. This is the "normal" stop process, as called from the | ||
2633 | 4197 | * goal change event. | ||
2634 | 4198 | */ | ||
2635 | 4199 | TEST_FEATURE ("with pre-stopping job and a goal of stop"); | ||
2636 | 4200 | job->goal = JOB_STOP; | ||
2637 | 4201 | job->state = JOB_PRE_STOPPING; | ||
2638 | 4202 | job->pid[PROCESS_MAIN] = 1; | ||
2639 | 4203 | |||
2640 | 4109 | TEST_EQ (job_next_state (job), JOB_PRE_STOP); | 4204 | TEST_EQ (job_next_state (job), JOB_PRE_STOP); |
2641 | 4110 | 4205 | ||
2642 | 4111 | 4206 | ||
2643 | @@ -4193,6 +4288,16 @@ | |||
2644 | 4193 | job->goal = JOB_START; | 4288 | job->goal = JOB_START; |
2645 | 4194 | job->state = JOB_KILLED; | 4289 | job->state = JOB_KILLED; |
2646 | 4195 | 4290 | ||
2647 | 4291 | TEST_EQ (job_next_state (job), JOB_POST_STOPPING); | ||
2648 | 4292 | |||
2649 | 4293 | |||
2650 | 4294 | /* Check that the next state if we're starting a post-stopping | ||
2651 | 4295 | * job is post-stop. | ||
2652 | 4296 | */ | ||
2653 | 4297 | TEST_FEATURE ("with post-stopping job and a goal of start"); | ||
2654 | 4298 | job->goal = JOB_START; | ||
2655 | 4299 | job->state = JOB_POST_STOPPING; | ||
2656 | 4300 | |||
2657 | 4196 | TEST_EQ (job_next_state (job), JOB_POST_STOP); | 4301 | TEST_EQ (job_next_state (job), JOB_POST_STOP); |
2658 | 4197 | 4302 | ||
2659 | 4198 | 4303 | ||
2660 | @@ -4203,6 +4308,16 @@ | |||
2661 | 4203 | job->goal = JOB_STOP; | 4308 | job->goal = JOB_STOP; |
2662 | 4204 | job->state = JOB_KILLED; | 4309 | job->state = JOB_KILLED; |
2663 | 4205 | 4310 | ||
2664 | 4311 | TEST_EQ (job_next_state (job), JOB_POST_STOPPING); | ||
2665 | 4312 | |||
2666 | 4313 | |||
2667 | 4314 | /* Check that the next state if we're stopping a post-stopping | ||
2668 | 4315 | * job is post-stop. | ||
2669 | 4316 | */ | ||
2670 | 4317 | TEST_FEATURE ("with post-stopping job and a goal of stop"); | ||
2671 | 4318 | job->goal = JOB_STOP; | ||
2672 | 4319 | job->state = JOB_POST_STOPPING; | ||
2673 | 4320 | |||
2674 | 4206 | TEST_EQ (job_next_state (job), JOB_POST_STOP); | 4321 | TEST_EQ (job_next_state (job), JOB_POST_STOP); |
2675 | 4207 | 4322 | ||
2676 | 4208 | 4323 | ||
2677 | 4209 | 4324 | ||
2678 | === modified file 'init/tests/test_job_process.c' | |||
2679 | --- init/tests/test_job_process.c 2013-11-11 10:13:08 +0000 | |||
2680 | +++ init/tests/test_job_process.c 2014-05-22 13:31:23 +0000 | |||
2681 | @@ -1,3 +1,6 @@ | |||
2682 | 1 | /* | ||
2683 | 2 | * FIXME: test_job_process has been left behind | ||
2684 | 3 | */ | ||
2685 | 1 | /* upstart | 4 | /* upstart |
2686 | 2 | * | 5 | * |
2687 | 3 | * test_job_process.c - test suite for init/job_process.c | 6 | * test_job_process.c - test suite for init/job_process.c |
2688 | @@ -147,33 +150,6 @@ | |||
2689 | 147 | static int get_available_pty_count (void) __attribute__((unused)); | 150 | static int get_available_pty_count (void) __attribute__((unused)); |
2690 | 148 | static void close_all_files (void); | 151 | static void close_all_files (void); |
2691 | 149 | 152 | ||
2692 | 150 | /** | ||
2693 | 151 | * fd_valid: | ||
2694 | 152 | * @fd: file descriptor. | ||
2695 | 153 | * | ||
2696 | 154 | * Return 1 if @fd is valid, else 0. | ||
2697 | 155 | **/ | ||
2698 | 156 | static int | ||
2699 | 157 | fd_valid (int fd) | ||
2700 | 158 | { | ||
2701 | 159 | int flags = 0; | ||
2702 | 160 | |||
2703 | 161 | if (fd < 0) | ||
2704 | 162 | return 0; | ||
2705 | 163 | |||
2706 | 164 | errno = 0; | ||
2707 | 165 | flags = fcntl (fd, F_GETFL); | ||
2708 | 166 | |||
2709 | 167 | if (flags < 0) | ||
2710 | 168 | return 0; | ||
2711 | 169 | |||
2712 | 170 | /* redundant really */ | ||
2713 | 171 | if (errno == EBADF) | ||
2714 | 172 | return 0; | ||
2715 | 173 | |||
2716 | 174 | return 1; | ||
2717 | 175 | } | ||
2718 | 176 | |||
2719 | 177 | static void | 153 | static void |
2720 | 178 | child (enum child_tests test, | 154 | child (enum child_tests test, |
2721 | 179 | const char *filename) | 155 | const char *filename) |
2722 | @@ -409,7 +385,7 @@ | |||
2723 | 409 | * (Such tests are handled in the bundled test_user_sessions.sh script). | 385 | * (Such tests are handled in the bundled test_user_sessions.sh script). |
2724 | 410 | */ | 386 | */ |
2725 | 411 | void | 387 | void |
2727 | 412 | test_run (void) | 388 | test_start (void) |
2728 | 413 | { | 389 | { |
2729 | 414 | char dirname[PATH_MAX]; | 390 | char dirname[PATH_MAX]; |
2730 | 415 | JobClass *class = NULL; | 391 | JobClass *class = NULL; |
2731 | @@ -418,7 +394,7 @@ | |||
2732 | 418 | struct stat statbuf; | 394 | struct stat statbuf; |
2733 | 419 | char filename[PATH_MAX], buf[80]; | 395 | char filename[PATH_MAX], buf[80]; |
2734 | 420 | char function[PATH_MAX]; | 396 | char function[PATH_MAX]; |
2736 | 421 | int ret = -1, status, first; | 397 | int status; |
2737 | 422 | siginfo_t info; | 398 | siginfo_t info; |
2738 | 423 | char filebuf[1024]; | 399 | char filebuf[1024]; |
2739 | 424 | struct passwd *pwd; | 400 | struct passwd *pwd; |
2740 | @@ -433,7 +409,7 @@ | |||
2741 | 433 | log_unflushed_init (); | 409 | log_unflushed_init (); |
2742 | 434 | job_class_init (); | 410 | job_class_init (); |
2743 | 435 | 411 | ||
2745 | 436 | TEST_FUNCTION ("job_process_run"); | 412 | TEST_FUNCTION ("job_process_start"); |
2746 | 437 | 413 | ||
2747 | 438 | TEST_FILENAME (filename); | 414 | TEST_FILENAME (filename); |
2748 | 439 | program_name = "test"; | 415 | program_name = "test"; |
2749 | @@ -467,8 +443,7 @@ | |||
2750 | 467 | job->state = JOB_SPAWNED; | 443 | job->state = JOB_SPAWNED; |
2751 | 468 | } | 444 | } |
2752 | 469 | 445 | ||
2755 | 470 | ret = job_process_run (job, PROCESS_MAIN); | 446 | job_process_start (job, PROCESS_MAIN); |
2754 | 471 | TEST_EQ (ret, 0); | ||
2756 | 472 | 447 | ||
2757 | 473 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 448 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
2758 | 474 | 449 | ||
2759 | @@ -502,8 +477,7 @@ | |||
2760 | 502 | job->state = JOB_SPAWNED; | 477 | job->state = JOB_SPAWNED; |
2761 | 503 | } | 478 | } |
2762 | 504 | 479 | ||
2765 | 505 | ret = job_process_run (job, PROCESS_MAIN); | 480 | job_process_start (job, PROCESS_MAIN); |
2764 | 506 | TEST_EQ (ret, 0); | ||
2766 | 507 | 481 | ||
2767 | 508 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 482 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
2768 | 509 | 483 | ||
2769 | @@ -544,8 +518,7 @@ | |||
2770 | 544 | job->state = JOB_SPAWNED; | 518 | job->state = JOB_SPAWNED; |
2771 | 545 | } | 519 | } |
2772 | 546 | 520 | ||
2775 | 547 | ret = job_process_run (job, PROCESS_MAIN); | 521 | job_process_start (job, PROCESS_MAIN); |
2774 | 548 | TEST_EQ (ret, 0); | ||
2776 | 549 | 522 | ||
2777 | 550 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 523 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
2778 | 551 | 524 | ||
2779 | @@ -584,8 +557,7 @@ | |||
2780 | 584 | job->state = JOB_SPAWNED; | 557 | job->state = JOB_SPAWNED; |
2781 | 585 | } | 558 | } |
2782 | 586 | 559 | ||
2785 | 587 | ret = job_process_run (job, PROCESS_MAIN); | 560 | job_process_start (job, PROCESS_MAIN); |
2784 | 588 | TEST_EQ (ret, 0); | ||
2786 | 589 | 561 | ||
2787 | 590 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 562 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
2788 | 591 | 563 | ||
2789 | @@ -625,8 +597,7 @@ | |||
2790 | 625 | job->state = JOB_SPAWNED; | 597 | job->state = JOB_SPAWNED; |
2791 | 626 | } | 598 | } |
2792 | 627 | 599 | ||
2795 | 628 | ret = job_process_run (job, PROCESS_MAIN); | 600 | job_process_start (job, PROCESS_MAIN); |
2794 | 629 | TEST_EQ (ret, 0); | ||
2796 | 630 | 601 | ||
2797 | 631 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 602 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
2798 | 632 | 603 | ||
2799 | @@ -672,8 +643,7 @@ | |||
2800 | 672 | "CRACKLE=FIZZ")); | 643 | "CRACKLE=FIZZ")); |
2801 | 673 | } | 644 | } |
2802 | 674 | 645 | ||
2805 | 675 | ret = job_process_run (job, PROCESS_MAIN); | 646 | job_process_start (job, PROCESS_MAIN); |
2804 | 676 | TEST_EQ (ret, 0); | ||
2806 | 677 | 647 | ||
2807 | 678 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 648 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
2808 | 679 | 649 | ||
2809 | @@ -728,8 +698,7 @@ | |||
2810 | 728 | "CRACKLE=FIZZ")); | 698 | "CRACKLE=FIZZ")); |
2811 | 729 | } | 699 | } |
2812 | 730 | 700 | ||
2815 | 731 | ret = job_process_run (job, PROCESS_MAIN); | 701 | job_process_start (job, PROCESS_MAIN); |
2814 | 732 | TEST_EQ (ret, 0); | ||
2816 | 733 | 702 | ||
2817 | 734 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 703 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
2818 | 735 | 704 | ||
2819 | @@ -785,8 +754,7 @@ | |||
2820 | 785 | "CRACKLE=FIZZ")); | 754 | "CRACKLE=FIZZ")); |
2821 | 786 | } | 755 | } |
2822 | 787 | 756 | ||
2825 | 788 | ret = job_process_run (job, PROCESS_PRE_STOP); | 757 | job_process_start (job, PROCESS_PRE_STOP); |
2824 | 789 | TEST_EQ (ret, 0); | ||
2826 | 790 | 758 | ||
2827 | 791 | TEST_NE (job->pid[PROCESS_PRE_STOP], 0); | 759 | TEST_NE (job->pid[PROCESS_PRE_STOP], 0); |
2828 | 792 | 760 | ||
2829 | @@ -843,8 +811,7 @@ | |||
2830 | 843 | "CRACKLE=FIZZ")); | 811 | "CRACKLE=FIZZ")); |
2831 | 844 | } | 812 | } |
2832 | 845 | 813 | ||
2835 | 846 | ret = job_process_run (job, PROCESS_POST_STOP); | 814 | job_process_start (job, PROCESS_POST_STOP); |
2834 | 847 | TEST_EQ (ret, 0); | ||
2836 | 848 | 815 | ||
2837 | 849 | TEST_NE (job->pid[PROCESS_POST_STOP], 0); | 816 | TEST_NE (job->pid[PROCESS_POST_STOP], 0); |
2838 | 850 | 817 | ||
2839 | @@ -894,36 +861,11 @@ | |||
2840 | 894 | job->state = JOB_SPAWNED; | 861 | job->state = JOB_SPAWNED; |
2841 | 895 | } | 862 | } |
2842 | 896 | 863 | ||
2845 | 897 | ret = job_process_run (job, PROCESS_MAIN); | 864 | job_process_start (job, PROCESS_MAIN); |
2844 | 898 | TEST_EQ (ret, 0); | ||
2846 | 899 | 865 | ||
2847 | 900 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 866 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
2848 | 901 | 867 | ||
2874 | 902 | /* Loop until we've fed all of the data. */ | 868 | TEST_WATCH_LOOP (); |
2850 | 903 | first = TRUE; | ||
2851 | 904 | for (;;) { | ||
2852 | 905 | fd_set readfds, writefds, exceptfds; | ||
2853 | 906 | int nfds; | ||
2854 | 907 | |||
2855 | 908 | nfds = 0; | ||
2856 | 909 | FD_ZERO (&readfds); | ||
2857 | 910 | FD_ZERO (&writefds); | ||
2858 | 911 | FD_ZERO (&exceptfds); | ||
2859 | 912 | |||
2860 | 913 | nih_io_select_fds (&nfds, &readfds, | ||
2861 | 914 | &writefds, &exceptfds); | ||
2862 | 915 | if (! nfds) { | ||
2863 | 916 | if (first) | ||
2864 | 917 | TEST_FAILED ("expected to have " | ||
2865 | 918 | "data to feed."); | ||
2866 | 919 | break; | ||
2867 | 920 | } | ||
2868 | 921 | first = FALSE; | ||
2869 | 922 | |||
2870 | 923 | select (nfds, &readfds, &writefds, &exceptfds, NULL); | ||
2871 | 924 | |||
2872 | 925 | nih_io_handle_fds (&readfds, &writefds, &exceptfds); | ||
2873 | 926 | } | ||
2875 | 927 | 869 | ||
2876 | 928 | waitpid (job->pid[PROCESS_MAIN], &status, 0); | 870 | waitpid (job->pid[PROCESS_MAIN], &status, 0); |
2877 | 929 | TEST_TRUE (WIFEXITED (status)); | 871 | TEST_TRUE (WIFEXITED (status)); |
2878 | @@ -962,8 +904,7 @@ | |||
2879 | 962 | job->trace_state = TRACE_NORMAL; | 904 | job->trace_state = TRACE_NORMAL; |
2880 | 963 | } | 905 | } |
2881 | 964 | 906 | ||
2884 | 965 | ret = job_process_run (job, PROCESS_MAIN); | 907 | job_process_start (job, PROCESS_MAIN); |
2883 | 966 | TEST_EQ (ret, 0); | ||
2885 | 967 | 908 | ||
2886 | 968 | TEST_EQ (job->trace_forks, 0); | 909 | TEST_EQ (job->trace_forks, 0); |
2887 | 969 | TEST_EQ (job->trace_state, TRACE_NONE); | 910 | TEST_EQ (job->trace_state, TRACE_NONE); |
2888 | @@ -1002,8 +943,7 @@ | |||
2889 | 1002 | job->trace_state = TRACE_NORMAL; | 943 | job->trace_state = TRACE_NORMAL; |
2890 | 1003 | } | 944 | } |
2891 | 1004 | 945 | ||
2894 | 1005 | ret = job_process_run (job, PROCESS_PRE_START); | 946 | job_process_start (job, PROCESS_PRE_START); |
2893 | 1006 | TEST_EQ (ret, 0); | ||
2895 | 1007 | 947 | ||
2896 | 1008 | TEST_EQ (job->trace_forks, 0); | 948 | TEST_EQ (job->trace_forks, 0); |
2897 | 1009 | TEST_EQ (job->trace_state, TRACE_NONE); | 949 | TEST_EQ (job->trace_state, TRACE_NONE); |
2898 | @@ -1044,8 +984,7 @@ | |||
2899 | 1044 | job->trace_state = TRACE_NORMAL; | 984 | job->trace_state = TRACE_NORMAL; |
2900 | 1045 | } | 985 | } |
2901 | 1046 | 986 | ||
2904 | 1047 | ret = job_process_run (job, PROCESS_MAIN); | 987 | job_process_start (job, PROCESS_MAIN); |
2903 | 1048 | TEST_EQ (ret, 0); | ||
2905 | 1049 | 988 | ||
2906 | 1050 | TEST_EQ (job->trace_forks, 0); | 989 | TEST_EQ (job->trace_forks, 0); |
2907 | 1051 | TEST_EQ (job->trace_state, TRACE_NEW); | 990 | TEST_EQ (job->trace_state, TRACE_NEW); |
2908 | @@ -1095,8 +1034,7 @@ | |||
2909 | 1095 | job->trace_state = TRACE_NORMAL; | 1034 | job->trace_state = TRACE_NORMAL; |
2910 | 1096 | } | 1035 | } |
2911 | 1097 | 1036 | ||
2914 | 1098 | ret = job_process_run (job, PROCESS_MAIN); | 1037 | job_process_start (job, PROCESS_MAIN); |
2913 | 1099 | TEST_EQ (ret, 0); | ||
2915 | 1100 | 1038 | ||
2916 | 1101 | TEST_EQ (job->trace_forks, 0); | 1039 | TEST_EQ (job->trace_forks, 0); |
2917 | 1102 | TEST_EQ (job->trace_state, TRACE_NEW); | 1040 | TEST_EQ (job->trace_state, TRACE_NEW); |
2918 | @@ -1122,7 +1060,7 @@ | |||
2919 | 1122 | } | 1060 | } |
2920 | 1123 | 1061 | ||
2921 | 1124 | /* Check that if we try and run a command that doesn't exist, | 1062 | /* Check that if we try and run a command that doesn't exist, |
2923 | 1125 | * job_process_run() raises a ProcessError and the command doesn't | 1063 | * job_process_start() raises a ProcessError and the command doesn't |
2924 | 1126 | * have any stored process id for it. | 1064 | * have any stored process id for it. |
2925 | 1127 | */ | 1065 | */ |
2926 | 1128 | TEST_FEATURE ("with no such file"); | 1066 | TEST_FEATURE ("with no such file"); |
2927 | @@ -1144,11 +1082,12 @@ | |||
2928 | 1144 | } | 1082 | } |
2929 | 1145 | 1083 | ||
2930 | 1146 | TEST_DIVERT_STDERR (output) { | 1084 | TEST_DIVERT_STDERR (output) { |
2932 | 1147 | ret = job_process_run (job, PROCESS_MAIN); | 1085 | job_process_start (job, PROCESS_MAIN); |
2933 | 1086 | TEST_WATCH_LOOP (); | ||
2934 | 1087 | event_poll (); | ||
2935 | 1148 | } | 1088 | } |
2936 | 1149 | rewind (output); | 1089 | rewind (output); |
2939 | 1150 | TEST_LT (ret, 0); | 1090 | |
2938 | 1151 | |||
2940 | 1152 | TEST_EQ (job->pid[PROCESS_MAIN], 0); | 1091 | TEST_EQ (job->pid[PROCESS_MAIN], 0); |
2941 | 1153 | 1092 | ||
2942 | 1154 | TEST_FILE_EQ (output, ("test: Failed to spawn test (foo) main " | 1093 | TEST_FILE_EQ (output, ("test: Failed to spawn test (foo) main " |
2943 | @@ -1195,8 +1134,7 @@ | |||
2944 | 1195 | job->goal = JOB_START; | 1134 | job->goal = JOB_START; |
2945 | 1196 | job->state = JOB_SPAWNED; | 1135 | job->state = JOB_SPAWNED; |
2946 | 1197 | 1136 | ||
2949 | 1198 | ret = job_process_run (job, PROCESS_MAIN); | 1137 | job_process_start (job, PROCESS_MAIN); |
2948 | 1199 | TEST_EQ (ret, 0); | ||
2950 | 1200 | 1138 | ||
2951 | 1201 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 1139 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
2952 | 1202 | 1140 | ||
2953 | @@ -1263,8 +1201,7 @@ | |||
2954 | 1263 | job->goal = JOB_START; | 1201 | job->goal = JOB_START; |
2955 | 1264 | job->state = JOB_SPAWNED; | 1202 | job->state = JOB_SPAWNED; |
2956 | 1265 | 1203 | ||
2959 | 1266 | ret = job_process_run (job, PROCESS_MAIN); | 1204 | job_process_start (job, PROCESS_MAIN); |
2958 | 1267 | TEST_EQ (ret, 0); | ||
2960 | 1268 | 1205 | ||
2961 | 1269 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 1206 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
2962 | 1270 | 1207 | ||
2963 | @@ -1331,8 +1268,7 @@ | |||
2964 | 1331 | job->goal = JOB_START; | 1268 | job->goal = JOB_START; |
2965 | 1332 | job->state = JOB_SPAWNED; | 1269 | job->state = JOB_SPAWNED; |
2966 | 1333 | 1270 | ||
2969 | 1334 | ret = job_process_run (job, PROCESS_MAIN); | 1271 | job_process_start (job, PROCESS_MAIN); |
2968 | 1335 | TEST_EQ (ret, 0); | ||
2970 | 1336 | 1272 | ||
2971 | 1337 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 1273 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
2972 | 1338 | 1274 | ||
2973 | @@ -1399,8 +1335,7 @@ | |||
2974 | 1399 | job->goal = JOB_START; | 1335 | job->goal = JOB_START; |
2975 | 1400 | job->state = JOB_SPAWNED; | 1336 | job->state = JOB_SPAWNED; |
2976 | 1401 | 1337 | ||
2979 | 1402 | ret = job_process_run (job, PROCESS_MAIN); | 1338 | job_process_start (job, PROCESS_MAIN); |
2978 | 1403 | TEST_EQ (ret, 0); | ||
2980 | 1404 | 1339 | ||
2981 | 1405 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 1340 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
2982 | 1406 | 1341 | ||
2983 | @@ -1462,8 +1397,7 @@ | |||
2984 | 1462 | job->goal = JOB_START; | 1397 | job->goal = JOB_START; |
2985 | 1463 | job->state = JOB_SPAWNED; | 1398 | job->state = JOB_SPAWNED; |
2986 | 1464 | 1399 | ||
2989 | 1465 | ret = job_process_run (job, PROCESS_MAIN); | 1400 | job_process_start (job, PROCESS_MAIN); |
2988 | 1466 | TEST_EQ (ret, 0); | ||
2990 | 1467 | 1401 | ||
2991 | 1468 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 1402 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
2992 | 1469 | 1403 | ||
2993 | @@ -1499,8 +1433,7 @@ | |||
2994 | 1499 | job->goal = JOB_START; | 1433 | job->goal = JOB_START; |
2995 | 1500 | job->state = JOB_SPAWNED; | 1434 | job->state = JOB_SPAWNED; |
2996 | 1501 | 1435 | ||
2999 | 1502 | ret = job_process_run (job, PROCESS_MAIN); | 1436 | job_process_start (job, PROCESS_MAIN); |
2998 | 1503 | TEST_EQ (ret, 0); | ||
3000 | 1504 | 1437 | ||
3001 | 1505 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 1438 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3002 | 1506 | 1439 | ||
3003 | @@ -1536,8 +1469,7 @@ | |||
3004 | 1536 | job->goal = JOB_START; | 1469 | job->goal = JOB_START; |
3005 | 1537 | job->state = JOB_SPAWNED; | 1470 | job->state = JOB_SPAWNED; |
3006 | 1538 | 1471 | ||
3009 | 1539 | ret = job_process_run (job, PROCESS_MAIN); | 1472 | job_process_start (job, PROCESS_MAIN); |
3008 | 1540 | TEST_EQ (ret, 0); | ||
3010 | 1541 | 1473 | ||
3011 | 1542 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 1474 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3012 | 1543 | 1475 | ||
3013 | @@ -1583,11 +1515,13 @@ | |||
3014 | 1583 | job->goal = JOB_START; | 1515 | job->goal = JOB_START; |
3015 | 1584 | job->state = JOB_SPAWNED; | 1516 | job->state = JOB_SPAWNED; |
3016 | 1585 | 1517 | ||
3019 | 1586 | ret = job_process_run (job, PROCESS_MAIN); | 1518 | job_process_start (job, PROCESS_MAIN); |
3018 | 1587 | TEST_EQ (ret, 0); | ||
3020 | 1588 | 1519 | ||
3021 | 1589 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 1520 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3022 | 1590 | 1521 | ||
3023 | 1522 | /* XXX: call 0: async process setup */ | ||
3024 | 1523 | TEST_WATCH_UPDATE (); | ||
3025 | 1524 | |||
3026 | 1591 | /* XXX: call 1: wait for script write to child shell */ | 1525 | /* XXX: call 1: wait for script write to child shell */ |
3027 | 1592 | TEST_WATCH_UPDATE (); | 1526 | TEST_WATCH_UPDATE (); |
3028 | 1593 | 1527 | ||
3029 | @@ -1613,10 +1547,10 @@ | |||
3030 | 1613 | 1547 | ||
3031 | 1614 | /* Note we can't use TEST_ALLOC_FAIL() for this test since on | 1548 | /* Note we can't use TEST_ALLOC_FAIL() for this test since on |
3032 | 1615 | * the ENOMEM loop all we could do is discard the error and | 1549 | * the ENOMEM loop all we could do is discard the error and |
3034 | 1616 | * continue since job_process_run() calls job_process_spawn() | 1550 | * continue since job_process_start() calls job_process_spawn() |
3035 | 1617 | * repeatedly until it works, but the alloc fails in log_new() | 1551 | * repeatedly until it works, but the alloc fails in log_new() |
3036 | 1618 | * invoked by job_process_spawn() such that when we've left | 1552 | * invoked by job_process_spawn() such that when we've left |
3038 | 1619 | * job_process_run(), it's too late. | 1553 | * job_process_start(), it's too late. |
3039 | 1620 | * | 1554 | * |
3040 | 1621 | * However, we test this scenario in test_spawn() so all is not | 1555 | * However, we test this scenario in test_spawn() so all is not |
3041 | 1622 | * lost. | 1556 | * lost. |
3042 | @@ -1637,8 +1571,7 @@ | |||
3043 | 1637 | job->goal = JOB_START; | 1571 | job->goal = JOB_START; |
3044 | 1638 | job->state = JOB_SPAWNED; | 1572 | job->state = JOB_SPAWNED; |
3045 | 1639 | 1573 | ||
3048 | 1640 | ret = job_process_run (job, PROCESS_MAIN); | 1574 | job_process_start (job, PROCESS_MAIN); |
3047 | 1641 | TEST_EQ (ret, 0); | ||
3049 | 1642 | 1575 | ||
3050 | 1643 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 1576 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3051 | 1644 | 1577 | ||
3052 | @@ -1695,11 +1628,13 @@ | |||
3053 | 1695 | job->goal = JOB_START; | 1628 | job->goal = JOB_START; |
3054 | 1696 | job->state = JOB_SPAWNED; | 1629 | job->state = JOB_SPAWNED; |
3055 | 1697 | 1630 | ||
3058 | 1698 | ret = job_process_run (job, PROCESS_MAIN); | 1631 | job_process_start (job, PROCESS_MAIN); |
3057 | 1699 | TEST_EQ (ret, 0); | ||
3059 | 1700 | 1632 | ||
3060 | 1701 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 1633 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3061 | 1702 | 1634 | ||
3062 | 1635 | /* wait for process to setup */ | ||
3063 | 1636 | TEST_WATCH_UPDATE (); | ||
3064 | 1637 | |||
3065 | 1703 | /* wait for read from pty allowing logger to write to log file */ | 1638 | /* wait for read from pty allowing logger to write to log file */ |
3066 | 1704 | TEST_WATCH_UPDATE (); | 1639 | TEST_WATCH_UPDATE (); |
3067 | 1705 | 1640 | ||
3068 | @@ -1779,11 +1714,13 @@ | |||
3069 | 1779 | job->goal = JOB_START; | 1714 | job->goal = JOB_START; |
3070 | 1780 | job->state = JOB_SPAWNED; | 1715 | job->state = JOB_SPAWNED; |
3071 | 1781 | 1716 | ||
3074 | 1782 | ret = job_process_run (job, PROCESS_MAIN); | 1717 | job_process_start (job, PROCESS_MAIN); |
3073 | 1783 | TEST_EQ (ret, 0); | ||
3075 | 1784 | 1718 | ||
3076 | 1785 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 1719 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3077 | 1786 | 1720 | ||
3078 | 1721 | /* wait for process to setup */ | ||
3079 | 1722 | TEST_WATCH_UPDATE (); | ||
3080 | 1723 | |||
3081 | 1787 | /* wait for read from pty allowing logger to write to log file */ | 1724 | /* wait for read from pty allowing logger to write to log file */ |
3082 | 1788 | TEST_WATCH_UPDATE (); | 1725 | TEST_WATCH_UPDATE (); |
3083 | 1789 | 1726 | ||
3084 | @@ -1861,10 +1798,10 @@ | |||
3085 | 1861 | 1798 | ||
3086 | 1862 | /* Note we can't use TEST_ALLOC_FAIL() for this test since on | 1799 | /* Note we can't use TEST_ALLOC_FAIL() for this test since on |
3087 | 1863 | * the ENOMEM loop all we could do is discard the error and | 1800 | * the ENOMEM loop all we could do is discard the error and |
3089 | 1864 | * continue since job_process_run() calls job_process_spawn() | 1801 | * continue since job_process_start() calls job_process_spawn() |
3090 | 1865 | * repeatedly until it works, but the alloc fails in log_new() | 1802 | * repeatedly until it works, but the alloc fails in log_new() |
3091 | 1866 | * invoked by job_process_spawn() such that when we've left | 1803 | * invoked by job_process_spawn() such that when we've left |
3093 | 1867 | * job_process_run(), it's too late. | 1804 | * job_process_start(), it's too late. |
3094 | 1868 | * | 1805 | * |
3095 | 1869 | * However, we test this scenario in test_spawn() so all is not | 1806 | * However, we test this scenario in test_spawn() so all is not |
3096 | 1870 | * lost. | 1807 | * lost. |
3097 | @@ -1885,11 +1822,13 @@ | |||
3098 | 1885 | job->goal = JOB_START; | 1822 | job->goal = JOB_START; |
3099 | 1886 | job->state = JOB_SPAWNED; | 1823 | job->state = JOB_SPAWNED; |
3100 | 1887 | 1824 | ||
3103 | 1888 | ret = job_process_run (job, PROCESS_MAIN); | 1825 | job_process_start (job, PROCESS_MAIN); |
3102 | 1889 | TEST_EQ (ret, 0); | ||
3104 | 1890 | 1826 | ||
3105 | 1891 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 1827 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3106 | 1892 | 1828 | ||
3107 | 1829 | /* wait for process to setup */ | ||
3108 | 1830 | TEST_WATCH_UPDATE (); | ||
3109 | 1831 | |||
3110 | 1893 | /* XXX: call 1: wait for script write to child shell */ | 1832 | /* XXX: call 1: wait for script write to child shell */ |
3111 | 1894 | TEST_WATCH_UPDATE (); | 1833 | TEST_WATCH_UPDATE (); |
3112 | 1895 | 1834 | ||
3113 | @@ -1948,11 +1887,13 @@ | |||
3114 | 1948 | job->goal = JOB_START; | 1887 | job->goal = JOB_START; |
3115 | 1949 | job->state = JOB_SPAWNED; | 1888 | job->state = JOB_SPAWNED; |
3116 | 1950 | 1889 | ||
3119 | 1951 | ret = job_process_run (job, PROCESS_MAIN); | 1890 | job_process_start (job, PROCESS_MAIN); |
3118 | 1952 | TEST_EQ (ret, 0); | ||
3120 | 1953 | 1891 | ||
3121 | 1954 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 1892 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3122 | 1955 | 1893 | ||
3123 | 1894 | /* wait for process to setup */ | ||
3124 | 1895 | TEST_WATCH_UPDATE (); | ||
3125 | 1896 | |||
3126 | 1956 | /* wait for read from pty allowing logger to write to log file */ | 1897 | /* wait for read from pty allowing logger to write to log file */ |
3127 | 1957 | TEST_WATCH_UPDATE (); | 1898 | TEST_WATCH_UPDATE (); |
3128 | 1958 | 1899 | ||
3129 | @@ -2017,11 +1958,13 @@ | |||
3130 | 2017 | job->goal = JOB_START; | 1958 | job->goal = JOB_START; |
3131 | 2018 | job->state = JOB_SPAWNED; | 1959 | job->state = JOB_SPAWNED; |
3132 | 2019 | 1960 | ||
3135 | 2020 | ret = job_process_run (job, PROCESS_MAIN); | 1961 | job_process_start (job, PROCESS_MAIN); |
3134 | 2021 | TEST_EQ (ret, 0); | ||
3136 | 2022 | 1962 | ||
3137 | 2023 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 1963 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3138 | 2024 | 1964 | ||
3139 | 1965 | /* wait for process to setup */ | ||
3140 | 1966 | TEST_WATCH_UPDATE (); | ||
3141 | 1967 | |||
3142 | 2025 | /* XXX: call 1: wait for script write to child shell */ | 1968 | /* XXX: call 1: wait for script write to child shell */ |
3143 | 2026 | TEST_WATCH_UPDATE (); | 1969 | TEST_WATCH_UPDATE (); |
3144 | 2027 | 1970 | ||
3145 | @@ -2064,10 +2007,10 @@ | |||
3146 | 2064 | 2007 | ||
3147 | 2065 | /* Note we can't use TEST_ALLOC_FAIL() for this test since on | 2008 | /* Note we can't use TEST_ALLOC_FAIL() for this test since on |
3148 | 2066 | * the ENOMEM loop all we could do is discard the error and | 2009 | * the ENOMEM loop all we could do is discard the error and |
3150 | 2067 | * continue since job_process_run() calls job_process_spawn() | 2010 | * continue since job_process_start() calls job_process_spawn() |
3151 | 2068 | * repeatedly until it works, but the alloc fails in log_new() | 2011 | * repeatedly until it works, but the alloc fails in log_new() |
3152 | 2069 | * invoked by job_process_spawn() such that when we've left | 2012 | * invoked by job_process_spawn() such that when we've left |
3154 | 2070 | * job_process_run(), it's too late. | 2013 | * job_process_start(), it's too late. |
3155 | 2071 | * | 2014 | * |
3156 | 2072 | * However, we test this scenario in test_spawn() so all is not | 2015 | * However, we test this scenario in test_spawn() so all is not |
3157 | 2073 | * lost. | 2016 | * lost. |
3158 | @@ -2088,8 +2031,7 @@ | |||
3159 | 2088 | job->goal = JOB_START; | 2031 | job->goal = JOB_START; |
3160 | 2089 | job->state = JOB_SPAWNED; | 2032 | job->state = JOB_SPAWNED; |
3161 | 2090 | 2033 | ||
3164 | 2091 | ret = job_process_run (job, PROCESS_MAIN); | 2034 | job_process_start (job, PROCESS_MAIN); |
3163 | 2092 | TEST_EQ (ret, 0); | ||
3165 | 2093 | 2035 | ||
3166 | 2094 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 2036 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3167 | 2095 | 2037 | ||
3168 | @@ -2135,7 +2077,7 @@ | |||
3169 | 2135 | * XXX: TEST_WATCH_UPDATE() *TWICE* to ensure select(2) is | 2077 | * XXX: TEST_WATCH_UPDATE() *TWICE* to ensure select(2) is |
3170 | 2136 | * XXX: called twice. | 2078 | * XXX: called twice. |
3171 | 2137 | * | 2079 | * |
3173 | 2138 | * This is required since job_process_run() uses an NihIo object | 2080 | * This is required since job_process_start() uses an NihIo object |
3174 | 2139 | * to squirt the script to the shell sub-process and this | 2081 | * to squirt the script to the shell sub-process and this |
3175 | 2140 | * triggers select to return when the data is written to the shell. | 2082 | * triggers select to return when the data is written to the shell. |
3176 | 2141 | * However, we don't care about that directly - we care more about | 2083 | * However, we don't care about that directly - we care more about |
3177 | @@ -2144,7 +2086,7 @@ | |||
3178 | 2144 | * written. | 2086 | * written. |
3179 | 2145 | * | 2087 | * |
3180 | 2146 | * Note that the 2nd call to TEST_WATCH_UPDATE would not be | 2088 | * Note that the 2nd call to TEST_WATCH_UPDATE would not be |
3182 | 2147 | * required should job_process_run() simple invoke write(2) to | 2089 | * required should job_process_start() simple invoke write(2) to |
3183 | 2148 | * send the data. | 2090 | * send the data. |
3184 | 2149 | */ | 2091 | */ |
3185 | 2150 | 2092 | ||
3186 | @@ -2165,11 +2107,13 @@ | |||
3187 | 2165 | job->goal = JOB_START; | 2107 | job->goal = JOB_START; |
3188 | 2166 | job->state = JOB_SPAWNED; | 2108 | job->state = JOB_SPAWNED; |
3189 | 2167 | 2109 | ||
3192 | 2168 | ret = job_process_run (job, PROCESS_MAIN); | 2110 | job_process_start (job, PROCESS_MAIN); |
3191 | 2169 | TEST_EQ (ret, 0); | ||
3193 | 2170 | 2111 | ||
3194 | 2171 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 2112 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3195 | 2172 | 2113 | ||
3196 | 2114 | /* wait for process to setup */ | ||
3197 | 2115 | TEST_WATCH_UPDATE (); | ||
3198 | 2116 | |||
3199 | 2173 | /* XXX: call 1: wait for script write to child shell */ | 2117 | /* XXX: call 1: wait for script write to child shell */ |
3200 | 2174 | TEST_WATCH_UPDATE (); | 2118 | TEST_WATCH_UPDATE (); |
3201 | 2175 | 2119 | ||
3202 | @@ -2227,8 +2171,7 @@ | |||
3203 | 2227 | job->goal = JOB_START; | 2171 | job->goal = JOB_START; |
3204 | 2228 | job->state = JOB_SPAWNED; | 2172 | job->state = JOB_SPAWNED; |
3205 | 2229 | 2173 | ||
3208 | 2230 | ret = job_process_run (job, PROCESS_MAIN); | 2174 | job_process_start (job, PROCESS_MAIN); |
3207 | 2231 | TEST_EQ (ret, 0); | ||
3209 | 2232 | 2175 | ||
3210 | 2233 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 2176 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3211 | 2234 | 2177 | ||
3212 | @@ -2287,8 +2230,7 @@ | |||
3213 | 2287 | job->goal = JOB_START; | 2230 | job->goal = JOB_START; |
3214 | 2288 | job->state = JOB_SPAWNED; | 2231 | job->state = JOB_SPAWNED; |
3215 | 2289 | 2232 | ||
3218 | 2290 | ret = job_process_run (job, PROCESS_MAIN); | 2233 | job_process_start (job, PROCESS_MAIN); |
3217 | 2291 | TEST_EQ (ret, 0); | ||
3219 | 2292 | 2234 | ||
3220 | 2293 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 2235 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3221 | 2294 | 2236 | ||
3222 | @@ -2352,8 +2294,7 @@ | |||
3223 | 2352 | job->goal = JOB_START; | 2294 | job->goal = JOB_START; |
3224 | 2353 | job->state = JOB_SPAWNED; | 2295 | job->state = JOB_SPAWNED; |
3225 | 2354 | 2296 | ||
3228 | 2355 | ret = job_process_run (job, PROCESS_MAIN); | 2297 | job_process_start (job, PROCESS_MAIN); |
3227 | 2356 | TEST_EQ (ret, 0); | ||
3229 | 2357 | 2298 | ||
3230 | 2358 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 2299 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3231 | 2359 | 2300 | ||
3232 | @@ -2414,12 +2355,12 @@ | |||
3233 | 2414 | job->goal = JOB_START; | 2355 | job->goal = JOB_START; |
3234 | 2415 | job->state = JOB_SPAWNED; | 2356 | job->state = JOB_SPAWNED; |
3235 | 2416 | 2357 | ||
3238 | 2417 | ret = job_process_run (job, PROCESS_MAIN); | 2358 | job_process_start (job, PROCESS_MAIN); |
3237 | 2418 | TEST_EQ (ret, 0); | ||
3239 | 2419 | 2359 | ||
3240 | 2420 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 2360 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3241 | 2421 | 2361 | ||
3242 | 2422 | TEST_WATCH_UPDATE (); | 2362 | TEST_WATCH_UPDATE (); |
3243 | 2363 | TEST_WATCH_UPDATE (); | ||
3244 | 2423 | waitpid (job->pid[PROCESS_MAIN], &status, 0); | 2364 | waitpid (job->pid[PROCESS_MAIN], &status, 0); |
3245 | 2424 | TEST_TRUE (WIFEXITED (status)); | 2365 | TEST_TRUE (WIFEXITED (status)); |
3246 | 2425 | TEST_EQ (WEXITSTATUS (status), 0); | 2366 | TEST_EQ (WEXITSTATUS (status), 0); |
3247 | @@ -2474,8 +2415,7 @@ | |||
3248 | 2474 | job->goal = JOB_START; | 2415 | job->goal = JOB_START; |
3249 | 2475 | job->state = JOB_SPAWNED; | 2416 | job->state = JOB_SPAWNED; |
3250 | 2476 | 2417 | ||
3253 | 2477 | ret = job_process_run (job, PROCESS_MAIN); | 2418 | job_process_start (job, PROCESS_MAIN); |
3252 | 2478 | TEST_EQ (ret, 0); | ||
3254 | 2479 | 2419 | ||
3255 | 2480 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 2420 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3256 | 2481 | 2421 | ||
3257 | @@ -2537,8 +2477,7 @@ | |||
3258 | 2537 | job->goal = JOB_START; | 2477 | job->goal = JOB_START; |
3259 | 2538 | job->state = JOB_SPAWNED; | 2478 | job->state = JOB_SPAWNED; |
3260 | 2539 | 2479 | ||
3263 | 2540 | ret = job_process_run (job, PROCESS_MAIN); | 2480 | job_process_start (job, PROCESS_MAIN); |
3262 | 2541 | TEST_EQ (ret, 0); | ||
3264 | 2542 | 2481 | ||
3265 | 2543 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 2482 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3266 | 2544 | 2483 | ||
3267 | @@ -2597,12 +2536,12 @@ | |||
3268 | 2597 | job->goal = JOB_START; | 2536 | job->goal = JOB_START; |
3269 | 2598 | job->state = JOB_SPAWNED; | 2537 | job->state = JOB_SPAWNED; |
3270 | 2599 | 2538 | ||
3273 | 2600 | ret = job_process_run (job, PROCESS_MAIN); | 2539 | job_process_start (job, PROCESS_MAIN); |
3272 | 2601 | TEST_EQ (ret, 0); | ||
3274 | 2602 | 2540 | ||
3275 | 2603 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 2541 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3276 | 2604 | 2542 | ||
3277 | 2605 | TEST_WATCH_UPDATE (); | 2543 | TEST_WATCH_UPDATE (); |
3278 | 2544 | TEST_WATCH_UPDATE (); | ||
3279 | 2606 | 2545 | ||
3280 | 2607 | waitpid (job->pid[PROCESS_MAIN], &status, 0); | 2546 | waitpid (job->pid[PROCESS_MAIN], &status, 0); |
3281 | 2608 | TEST_TRUE (WIFEXITED (status)); | 2547 | TEST_TRUE (WIFEXITED (status)); |
3282 | @@ -2659,8 +2598,7 @@ | |||
3283 | 2659 | job->goal = JOB_START; | 2598 | job->goal = JOB_START; |
3284 | 2660 | job->state = JOB_SPAWNED; | 2599 | job->state = JOB_SPAWNED; |
3285 | 2661 | 2600 | ||
3288 | 2662 | ret = job_process_run (job, PROCESS_MAIN); | 2601 | job_process_start (job, PROCESS_MAIN); |
3287 | 2663 | TEST_EQ (ret, 0); | ||
3289 | 2664 | 2602 | ||
3290 | 2665 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 2603 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3291 | 2666 | 2604 | ||
3292 | @@ -2725,8 +2663,7 @@ | |||
3293 | 2725 | job->goal = JOB_START; | 2663 | job->goal = JOB_START; |
3294 | 2726 | job->state = JOB_SPAWNED; | 2664 | job->state = JOB_SPAWNED; |
3295 | 2727 | 2665 | ||
3298 | 2728 | ret = job_process_run (job, PROCESS_MAIN); | 2666 | job_process_start (job, PROCESS_MAIN); |
3297 | 2729 | TEST_EQ (ret, 0); | ||
3299 | 2730 | 2667 | ||
3300 | 2731 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 2668 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3301 | 2732 | 2669 | ||
3302 | @@ -2787,12 +2724,12 @@ | |||
3303 | 2787 | job->goal = JOB_START; | 2724 | job->goal = JOB_START; |
3304 | 2788 | job->state = JOB_SPAWNED; | 2725 | job->state = JOB_SPAWNED; |
3305 | 2789 | 2726 | ||
3308 | 2790 | ret = job_process_run (job, PROCESS_MAIN); | 2727 | job_process_start (job, PROCESS_MAIN); |
3307 | 2791 | TEST_EQ (ret, 0); | ||
3309 | 2792 | 2728 | ||
3310 | 2793 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 2729 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3311 | 2794 | 2730 | ||
3312 | 2795 | TEST_WATCH_UPDATE (); | 2731 | TEST_WATCH_UPDATE (); |
3313 | 2732 | TEST_WATCH_UPDATE (); | ||
3314 | 2796 | 2733 | ||
3315 | 2797 | waitpid (job->pid[PROCESS_MAIN], &status, 0); | 2734 | waitpid (job->pid[PROCESS_MAIN], &status, 0); |
3316 | 2798 | TEST_TRUE (WIFEXITED (status)); | 2735 | TEST_TRUE (WIFEXITED (status)); |
3317 | @@ -2851,8 +2788,7 @@ | |||
3318 | 2851 | job->goal = JOB_START; | 2788 | job->goal = JOB_START; |
3319 | 2852 | job->state = JOB_SPAWNED; | 2789 | job->state = JOB_SPAWNED; |
3320 | 2853 | 2790 | ||
3323 | 2854 | ret = job_process_run (job, PROCESS_MAIN); | 2791 | job_process_start (job, PROCESS_MAIN); |
3322 | 2855 | TEST_EQ (ret, 0); | ||
3324 | 2856 | 2792 | ||
3325 | 2857 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 2793 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3326 | 2858 | 2794 | ||
3327 | @@ -2913,8 +2849,7 @@ | |||
3328 | 2913 | job->goal = JOB_START; | 2849 | job->goal = JOB_START; |
3329 | 2914 | job->state = JOB_SPAWNED; | 2850 | job->state = JOB_SPAWNED; |
3330 | 2915 | 2851 | ||
3333 | 2916 | ret = job_process_run (job, PROCESS_MAIN); | 2852 | job_process_start (job, PROCESS_MAIN); |
3332 | 2917 | TEST_EQ (ret, 0); | ||
3334 | 2918 | 2853 | ||
3335 | 2919 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 2854 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3336 | 2920 | 2855 | ||
3337 | @@ -2973,8 +2908,7 @@ | |||
3338 | 2973 | job->goal = JOB_START; | 2908 | job->goal = JOB_START; |
3339 | 2974 | job->state = JOB_SPAWNED; | 2909 | job->state = JOB_SPAWNED; |
3340 | 2975 | 2910 | ||
3343 | 2976 | ret = job_process_run (job, PROCESS_MAIN); | 2911 | job_process_start (job, PROCESS_MAIN); |
3342 | 2977 | TEST_EQ (ret, 0); | ||
3344 | 2978 | 2912 | ||
3345 | 2979 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 2913 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3346 | 2980 | 2914 | ||
3347 | @@ -3037,8 +2971,7 @@ | |||
3348 | 3037 | job->goal = JOB_START; | 2971 | job->goal = JOB_START; |
3349 | 3038 | job->state = JOB_SPAWNED; | 2972 | job->state = JOB_SPAWNED; |
3350 | 3039 | 2973 | ||
3353 | 3040 | ret = job_process_run (job, PROCESS_MAIN); | 2974 | job_process_start (job, PROCESS_MAIN); |
3352 | 3041 | TEST_EQ (ret, 0); | ||
3354 | 3042 | 2975 | ||
3355 | 3043 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 2976 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3356 | 3044 | 2977 | ||
3357 | @@ -3112,8 +3045,9 @@ | |||
3358 | 3112 | output = tmpfile (); | 3045 | output = tmpfile (); |
3359 | 3113 | TEST_NE_P (output, NULL); | 3046 | TEST_NE_P (output, NULL); |
3360 | 3114 | TEST_DIVERT_STDERR (output) { | 3047 | TEST_DIVERT_STDERR (output) { |
3363 | 3115 | ret = job_process_run (job, PROCESS_MAIN); | 3048 | job_process_start (job, PROCESS_MAIN); |
3364 | 3116 | TEST_LT (ret, 0); | 3049 | TEST_WATCH_UPDATE (); |
3365 | 3050 | event_poll (); | ||
3366 | 3117 | } | 3051 | } |
3367 | 3118 | fclose (output); | 3052 | fclose (output); |
3368 | 3119 | 3053 | ||
3369 | @@ -3161,8 +3095,8 @@ | |||
3370 | 3161 | job->goal = JOB_START; | 3095 | job->goal = JOB_START; |
3371 | 3162 | job->state = JOB_SPAWNED; | 3096 | job->state = JOB_SPAWNED; |
3372 | 3163 | 3097 | ||
3375 | 3164 | ret = job_process_run (job, PROCESS_MAIN); | 3098 | job_process_start (job, PROCESS_MAIN); |
3376 | 3165 | TEST_LT (ret, 0); | 3099 | TEST_WATCH_UPDATE (); |
3377 | 3166 | 3100 | ||
3378 | 3167 | /* We don't expect a logfile to be written since there is no | 3101 | /* We don't expect a logfile to be written since there is no |
3379 | 3168 | * accompanying shell to write the error. | 3102 | * accompanying shell to write the error. |
3380 | @@ -3173,10 +3107,10 @@ | |||
3381 | 3173 | job->goal = JOB_STOP; | 3107 | job->goal = JOB_STOP; |
3382 | 3174 | job->state = JOB_POST_STOP; | 3108 | job->state = JOB_POST_STOP; |
3383 | 3175 | 3109 | ||
3386 | 3176 | ret = job_process_run (job, PROCESS_POST_STOP); | 3110 | job_process_start (job, PROCESS_POST_STOP); |
3385 | 3177 | TEST_EQ (ret, 0); | ||
3387 | 3178 | 3111 | ||
3388 | 3179 | TEST_NE (job->pid[PROCESS_POST_STOP], 0); | 3112 | TEST_NE (job->pid[PROCESS_POST_STOP], 0); |
3389 | 3113 | TEST_WATCH_UPDATE (); | ||
3390 | 3180 | 3114 | ||
3391 | 3181 | /* Flush the io so that the shell on the client side | 3115 | /* Flush the io so that the shell on the client side |
3392 | 3182 | * gets the data (the script to execute). | 3116 | * gets the data (the script to execute). |
3393 | @@ -3187,8 +3121,11 @@ | |||
3394 | 3187 | TEST_TRUE (WIFEXITED (status)); | 3121 | TEST_TRUE (WIFEXITED (status)); |
3395 | 3188 | TEST_EQ (WEXITSTATUS (status), 0); | 3122 | TEST_EQ (WEXITSTATUS (status), 0); |
3396 | 3189 | 3123 | ||
3397 | 3124 | TEST_WATCH_UPDATE (); | ||
3398 | 3125 | |||
3399 | 3190 | /* .. but the post stop should have written data */ | 3126 | /* .. but the post stop should have written data */ |
3400 | 3191 | TEST_EQ (stat (filename, &statbuf), 0); | 3127 | TEST_EQ (stat (filename, &statbuf), 0); |
3401 | 3128 | event_poll (); | ||
3402 | 3192 | } | 3129 | } |
3403 | 3193 | fclose (output); | 3130 | fclose (output); |
3404 | 3194 | 3131 | ||
3405 | @@ -3241,8 +3178,9 @@ | |||
3406 | 3241 | job->goal = JOB_START; | 3178 | job->goal = JOB_START; |
3407 | 3242 | job->state = JOB_SPAWNED; | 3179 | job->state = JOB_SPAWNED; |
3408 | 3243 | 3180 | ||
3411 | 3244 | ret = job_process_run (job, PROCESS_MAIN); | 3181 | job_process_start (job, PROCESS_MAIN); |
3412 | 3245 | TEST_LT (ret, 0); | 3182 | TEST_WATCH_UPDATE (); |
3413 | 3183 | TEST_WATCH_UPDATE (); | ||
3414 | 3246 | 3184 | ||
3415 | 3247 | /* We don't expect a logfile to be written since there is no | 3185 | /* We don't expect a logfile to be written since there is no |
3416 | 3248 | * accompanying shell to write the error. | 3186 | * accompanying shell to write the error. |
3417 | @@ -3253,8 +3191,8 @@ | |||
3418 | 3253 | job->goal = JOB_STOP; | 3191 | job->goal = JOB_STOP; |
3419 | 3254 | job->state = JOB_POST_STOP; | 3192 | job->state = JOB_POST_STOP; |
3420 | 3255 | 3193 | ||
3423 | 3256 | ret = job_process_run (job, PROCESS_POST_STOP); | 3194 | job_process_start (job, PROCESS_POST_STOP); |
3424 | 3257 | TEST_EQ (ret, 0); | 3195 | TEST_WATCH_UPDATE (); |
3425 | 3258 | 3196 | ||
3426 | 3259 | TEST_NE (job->pid[PROCESS_POST_STOP], 0); | 3197 | TEST_NE (job->pid[PROCESS_POST_STOP], 0); |
3427 | 3260 | 3198 | ||
3428 | @@ -3272,6 +3210,7 @@ | |||
3429 | 3272 | 3210 | ||
3430 | 3273 | /* .. but the post stop should have written data */ | 3211 | /* .. but the post stop should have written data */ |
3431 | 3274 | TEST_EQ (stat (filename, &statbuf), 0); | 3212 | TEST_EQ (stat (filename, &statbuf), 0); |
3432 | 3213 | event_poll (); | ||
3433 | 3275 | } | 3214 | } |
3434 | 3276 | fclose (output); | 3215 | fclose (output); |
3435 | 3277 | 3216 | ||
3436 | @@ -3325,8 +3264,8 @@ | |||
3437 | 3325 | job->goal = JOB_START; | 3264 | job->goal = JOB_START; |
3438 | 3326 | job->state = JOB_SPAWNED; | 3265 | job->state = JOB_SPAWNED; |
3439 | 3327 | 3266 | ||
3442 | 3328 | ret = job_process_run (job, PROCESS_MAIN); | 3267 | job_process_start (job, PROCESS_MAIN); |
3443 | 3329 | TEST_LT (ret, 0); | 3268 | TEST_WATCH_UPDATE (); |
3444 | 3330 | 3269 | ||
3445 | 3331 | /* We don't expect a logfile to be written since there is no | 3270 | /* We don't expect a logfile to be written since there is no |
3446 | 3332 | * accompanying shell to write the error. | 3271 | * accompanying shell to write the error. |
3447 | @@ -3337,8 +3276,8 @@ | |||
3448 | 3337 | job->goal = JOB_STOP; | 3276 | job->goal = JOB_STOP; |
3449 | 3338 | job->state = JOB_POST_STOP; | 3277 | job->state = JOB_POST_STOP; |
3450 | 3339 | 3278 | ||
3453 | 3340 | ret = job_process_run (job, PROCESS_POST_STOP); | 3279 | job_process_start (job, PROCESS_POST_STOP); |
3454 | 3341 | TEST_EQ (ret, 0); | 3280 | TEST_WATCH_UPDATE (); |
3455 | 3342 | 3281 | ||
3456 | 3343 | TEST_NE (job->pid[PROCESS_POST_STOP], 0); | 3282 | TEST_NE (job->pid[PROCESS_POST_STOP], 0); |
3457 | 3344 | 3283 | ||
3458 | @@ -3351,8 +3290,11 @@ | |||
3459 | 3351 | TEST_TRUE (WIFEXITED (status)); | 3290 | TEST_TRUE (WIFEXITED (status)); |
3460 | 3352 | TEST_EQ (WEXITSTATUS (status), 0); | 3291 | TEST_EQ (WEXITSTATUS (status), 0); |
3461 | 3353 | 3292 | ||
3462 | 3293 | TEST_WATCH_UPDATE (); | ||
3463 | 3294 | |||
3464 | 3354 | /* .. but the post stop should have written data */ | 3295 | /* .. but the post stop should have written data */ |
3465 | 3355 | TEST_EQ (stat (filename, &statbuf), 0); | 3296 | TEST_EQ (stat (filename, &statbuf), 0); |
3466 | 3297 | event_poll (); | ||
3467 | 3356 | } | 3298 | } |
3468 | 3357 | fclose (output); | 3299 | fclose (output); |
3469 | 3358 | 3300 | ||
3470 | @@ -3405,8 +3347,8 @@ | |||
3471 | 3405 | job->goal = JOB_START; | 3347 | job->goal = JOB_START; |
3472 | 3406 | job->state = JOB_SPAWNED; | 3348 | job->state = JOB_SPAWNED; |
3473 | 3407 | 3349 | ||
3476 | 3408 | ret = job_process_run (job, PROCESS_MAIN); | 3350 | job_process_start (job, PROCESS_MAIN); |
3477 | 3409 | TEST_LT (ret, 0); | 3351 | TEST_WATCH_UPDATE (); |
3478 | 3410 | 3352 | ||
3479 | 3411 | /* We don't expect a logfile to be written since there is no | 3353 | /* We don't expect a logfile to be written since there is no |
3480 | 3412 | * accompanying shell to write the error. | 3354 | * accompanying shell to write the error. |
3481 | @@ -3417,12 +3359,13 @@ | |||
3482 | 3417 | job->goal = JOB_STOP; | 3359 | job->goal = JOB_STOP; |
3483 | 3418 | job->state = JOB_POST_STOP; | 3360 | job->state = JOB_POST_STOP; |
3484 | 3419 | 3361 | ||
3487 | 3420 | ret = job_process_run (job, PROCESS_POST_STOP); | 3362 | job_process_start (job, PROCESS_POST_STOP); |
3488 | 3421 | TEST_LT (ret, 0); | 3363 | TEST_WATCH_UPDATE (); |
3489 | 3422 | 3364 | ||
3490 | 3423 | /* Again, no file expected */ | 3365 | /* Again, no file expected */ |
3491 | 3424 | TEST_EQ (stat (filename, &statbuf), -1); | 3366 | TEST_EQ (stat (filename, &statbuf), -1); |
3492 | 3425 | TEST_EQ (errno, ENOENT); | 3367 | TEST_EQ (errno, ENOENT); |
3493 | 3368 | event_poll (); | ||
3494 | 3426 | } | 3369 | } |
3495 | 3427 | fclose (output); | 3370 | fclose (output); |
3496 | 3428 | nih_free (class); | 3371 | nih_free (class); |
3497 | @@ -3463,8 +3406,7 @@ | |||
3498 | 3463 | job->goal = JOB_START; | 3406 | job->goal = JOB_START; |
3499 | 3464 | job->state = JOB_SPAWNED; | 3407 | job->state = JOB_SPAWNED; |
3500 | 3465 | 3408 | ||
3503 | 3466 | ret = job_process_run (job, PROCESS_MAIN); | 3409 | job_process_start (job, PROCESS_MAIN); |
3502 | 3467 | TEST_EQ (ret, 0); | ||
3504 | 3468 | 3410 | ||
3505 | 3469 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 3411 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3506 | 3470 | 3412 | ||
3507 | @@ -3483,8 +3425,8 @@ | |||
3508 | 3483 | job->goal = JOB_STOP; | 3425 | job->goal = JOB_STOP; |
3509 | 3484 | job->state = JOB_POST_STOP; | 3426 | job->state = JOB_POST_STOP; |
3510 | 3485 | 3427 | ||
3513 | 3486 | ret = job_process_run (job, PROCESS_POST_STOP); | 3428 | job_process_start (job, PROCESS_POST_STOP); |
3514 | 3487 | TEST_LT (ret, 0); | 3429 | TEST_WATCH_UPDATE (); |
3515 | 3488 | 3430 | ||
3516 | 3489 | TEST_EQ (job->pid[PROCESS_POST_STOP], 0); | 3431 | TEST_EQ (job->pid[PROCESS_POST_STOP], 0); |
3517 | 3490 | } | 3432 | } |
3518 | @@ -3524,8 +3466,8 @@ | |||
3519 | 3524 | job->goal = JOB_START; | 3466 | job->goal = JOB_START; |
3520 | 3525 | job->state = JOB_SPAWNED; | 3467 | job->state = JOB_SPAWNED; |
3521 | 3526 | 3468 | ||
3524 | 3527 | ret = job_process_run (job, PROCESS_MAIN); | 3469 | job_process_start (job, PROCESS_MAIN); |
3525 | 3528 | TEST_EQ (ret, 0); | 3470 | TEST_WATCH_UPDATE (); |
3526 | 3529 | 3471 | ||
3527 | 3530 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 3472 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3528 | 3531 | 3473 | ||
3529 | @@ -3585,8 +3527,8 @@ | |||
3530 | 3585 | job->goal = JOB_START; | 3527 | job->goal = JOB_START; |
3531 | 3586 | job->state = JOB_SPAWNED; | 3528 | job->state = JOB_SPAWNED; |
3532 | 3587 | 3529 | ||
3535 | 3588 | ret = job_process_run (job, PROCESS_MAIN); | 3530 | job_process_start (job, PROCESS_MAIN); |
3536 | 3589 | TEST_EQ (ret, 0); | 3531 | TEST_WATCH_UPDATE (); |
3537 | 3590 | 3532 | ||
3538 | 3591 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 3533 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3539 | 3592 | 3534 | ||
3540 | @@ -3648,8 +3590,8 @@ | |||
3541 | 3648 | job->goal = JOB_START; | 3590 | job->goal = JOB_START; |
3542 | 3649 | job->state = JOB_SPAWNED; | 3591 | job->state = JOB_SPAWNED; |
3543 | 3650 | 3592 | ||
3546 | 3651 | ret = job_process_run (job, PROCESS_MAIN); | 3593 | job_process_start (job, PROCESS_MAIN); |
3547 | 3652 | TEST_EQ (ret, 0); | 3594 | TEST_WATCH_UPDATE (); |
3548 | 3653 | 3595 | ||
3549 | 3654 | TEST_NE (job->pid[PROCESS_MAIN], 0); | 3596 | TEST_NE (job->pid[PROCESS_MAIN], 0); |
3550 | 3655 | 3597 | ||
3551 | @@ -3728,8 +3670,7 @@ | |||
3552 | 3728 | job->goal = JOB_START; | 3670 | job->goal = JOB_START; |
3553 | 3729 | job->state = JOB_SPAWNED; | 3671 | job->state = JOB_SPAWNED; |
3554 | 3730 | 3672 | ||
3557 | 3731 | ret = job_process_run (job, PROCESS_MAIN); | 3673 | job_process_start (job, PROCESS_MAIN); |
3556 | 3732 | TEST_EQ (ret, 0); | ||
3558 | 3733 | 3674 | ||
3559 | 3734 | /* Wait for process to avoid any possibility of EAGAIN in | 3675 | /* Wait for process to avoid any possibility of EAGAIN in |
3560 | 3735 | * log_read_watch(). | 3676 | * log_read_watch(). |
3561 | @@ -3802,8 +3743,9 @@ | |||
3562 | 3802 | job->goal = JOB_START; | 3743 | job->goal = JOB_START; |
3563 | 3803 | job->state = JOB_SPAWNED; | 3744 | job->state = JOB_SPAWNED; |
3564 | 3804 | 3745 | ||
3567 | 3805 | ret = job_process_run (job, PROCESS_MAIN); | 3746 | job_process_start (job, PROCESS_MAIN); |
3568 | 3806 | TEST_EQ (ret, 0); | 3747 | TEST_WATCH_UPDATE (); |
3569 | 3748 | TEST_WATCH_UPDATE (); | ||
3570 | 3807 | 3749 | ||
3571 | 3808 | pid = job->pid[PROCESS_MAIN]; | 3750 | pid = job->pid[PROCESS_MAIN]; |
3572 | 3809 | 3751 | ||
3573 | @@ -3933,8 +3875,8 @@ | |||
3574 | 3933 | TEST_EQ_P (job->log[i], NULL); | 3875 | TEST_EQ_P (job->log[i], NULL); |
3575 | 3934 | } | 3876 | } |
3576 | 3935 | 3877 | ||
3579 | 3936 | ret = job_process_run (job, PROCESS_MAIN); | 3878 | job_process_start (job, PROCESS_MAIN); |
3580 | 3937 | TEST_EQ (ret, 0); | 3879 | TEST_WATCH_UPDATE (); |
3581 | 3938 | 3880 | ||
3582 | 3939 | pid = job->pid[PROCESS_MAIN]; | 3881 | pid = job->pid[PROCESS_MAIN]; |
3583 | 3940 | 3882 | ||
3584 | @@ -4006,8 +3948,7 @@ | |||
3585 | 4006 | } | 3948 | } |
3586 | 4007 | 3949 | ||
3587 | 4008 | TEST_DIVERT_STDERR (output) { | 3950 | TEST_DIVERT_STDERR (output) { |
3590 | 4009 | ret = job_process_run (job, PROCESS_MAIN); | 3951 | job_process_start (job, PROCESS_MAIN); |
3589 | 4010 | TEST_EQ (ret, 0); | ||
3591 | 4011 | } | 3952 | } |
3592 | 4012 | fclose (output); | 3953 | fclose (output); |
3593 | 4013 | 3954 | ||
3594 | @@ -4064,13 +4005,8 @@ | |||
3595 | 4064 | } | 4005 | } |
3596 | 4065 | 4006 | ||
3597 | 4066 | TEST_DIVERT_STDERR (output) { | 4007 | TEST_DIVERT_STDERR (output) { |
3605 | 4067 | ret = job_process_run (job, PROCESS_MAIN); | 4008 | job_process_start (job, PROCESS_MAIN); |
3606 | 4068 | if (geteuid() == 0 || getuid() == pwd->pw_uid) { | 4009 | TEST_WATCH_UPDATE (); |
3600 | 4069 | TEST_EQ (ret, 0); | ||
3601 | 4070 | } | ||
3602 | 4071 | else { | ||
3603 | 4072 | TEST_EQ (ret, -1); | ||
3604 | 4073 | } | ||
3607 | 4074 | } | 4010 | } |
3608 | 4075 | 4011 | ||
3609 | 4076 | if (geteuid() == 0 || getuid() == pwd->pw_uid) { | 4012 | if (geteuid() == 0 || getuid() == pwd->pw_uid) { |
3610 | @@ -4081,13 +4017,15 @@ | |||
3611 | 4081 | } | 4017 | } |
3612 | 4082 | else { | 4018 | else { |
3613 | 4083 | TEST_EQ (stat (filename, &statbuf), -1); | 4019 | TEST_EQ (stat (filename, &statbuf), -1); |
3614 | 4020 | event_poll (); | ||
3615 | 4084 | } | 4021 | } |
3616 | 4085 | 4022 | ||
3617 | 4086 | unlink (filename); | 4023 | unlink (filename); |
3618 | 4087 | nih_free (class); | 4024 | nih_free (class); |
3619 | 4088 | |||
3620 | 4089 | } | 4025 | } |
3621 | 4090 | 4026 | ||
3622 | 4027 | /* FIXME with async spawn this test is racy */ | ||
3623 | 4028 | |||
3624 | 4091 | /************************************************************/ | 4029 | /************************************************************/ |
3625 | 4092 | TEST_FEATURE ("with multiple processes and log"); | 4030 | TEST_FEATURE ("with multiple processes and log"); |
3626 | 4093 | TEST_HASH_EMPTY (job_classes); | 4031 | TEST_HASH_EMPTY (job_classes); |
3627 | @@ -4128,14 +4066,13 @@ | |||
3628 | 4128 | job->goal = JOB_START; | 4066 | job->goal = JOB_START; |
3629 | 4129 | job->state = JOB_SPAWNED; | 4067 | job->state = JOB_SPAWNED; |
3630 | 4130 | 4068 | ||
3634 | 4131 | ret = job_process_run (job, PROCESS_MAIN); | 4069 | job_process_start (job, PROCESS_MAIN); |
3635 | 4132 | TEST_EQ (ret, 0); | 4070 | while (stat (filename, &statbuf) != 0) { |
3636 | 4133 | 4071 | TEST_WATCH_UPDATE (); | |
3637 | 4072 | } | ||
3638 | 4134 | pid = job->pid[PROCESS_MAIN]; | 4073 | pid = job->pid[PROCESS_MAIN]; |
3639 | 4135 | TEST_GT (pid, 0); | 4074 | TEST_GT (pid, 0); |
3640 | 4136 | 4075 | ||
3641 | 4137 | TEST_WATCH_UPDATE (); | ||
3642 | 4138 | |||
3643 | 4139 | TEST_EQ (stat (filename, &statbuf), 0); | 4076 | TEST_EQ (stat (filename, &statbuf), 0); |
3644 | 4140 | 4077 | ||
3645 | 4141 | output = fopen (filename, "r"); | 4078 | output = fopen (filename, "r"); |
3646 | @@ -4148,8 +4085,8 @@ | |||
3647 | 4148 | 4085 | ||
3648 | 4149 | TEST_EQ (fclose (output), 0); | 4086 | TEST_EQ (fclose (output), 0); |
3649 | 4150 | 4087 | ||
3652 | 4151 | ret = job_process_run (job, PROCESS_POST_START); | 4088 | job_process_start (job, PROCESS_POST_START); |
3653 | 4152 | TEST_EQ (ret, 0); | 4089 | TEST_WATCH_UPDATE (); |
3654 | 4153 | 4090 | ||
3655 | 4154 | pid = job->pid[PROCESS_POST_START]; | 4091 | pid = job->pid[PROCESS_POST_START]; |
3656 | 4155 | TEST_GT (pid, 0); | 4092 | TEST_GT (pid, 0); |
3657 | @@ -4244,6 +4181,8 @@ | |||
3658 | 4244 | int status; | 4181 | int status; |
3659 | 4245 | struct stat statbuf; | 4182 | struct stat statbuf; |
3660 | 4246 | int ret; | 4183 | int ret; |
3661 | 4184 | int job_process_fd = -1; | ||
3662 | 4185 | nih_local NihIoBuffer *buffer = NULL; | ||
3663 | 4247 | 4186 | ||
3664 | 4248 | log_unflushed_init (); | 4187 | log_unflushed_init (); |
3665 | 4249 | 4188 | ||
3666 | @@ -4257,7 +4196,7 @@ | |||
3667 | 4257 | */ | 4196 | */ |
3668 | 4258 | TEST_EQ (setenv ("UPSTART_LOGDIR", dirname, 1), 0); | 4197 | TEST_EQ (setenv ("UPSTART_LOGDIR", dirname, 1), 0); |
3669 | 4259 | 4198 | ||
3671 | 4260 | TEST_FUNCTION ("job_process_spawn"); | 4199 | TEST_FUNCTION ("job_process_spawn_with_fd"); |
3672 | 4261 | TEST_FILENAME (filename); | 4200 | TEST_FILENAME (filename); |
3673 | 4262 | 4201 | ||
3674 | 4263 | args[0] = argv0; | 4202 | args[0] = argv0; |
3675 | @@ -4278,7 +4217,7 @@ | |||
3676 | 4278 | class->console = CONSOLE_NONE; | 4217 | class->console = CONSOLE_NONE; |
3677 | 4279 | job = job_new (class, ""); | 4218 | job = job_new (class, ""); |
3678 | 4280 | 4219 | ||
3680 | 4281 | pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN); | 4220 | pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3681 | 4282 | TEST_GT (pid, 0); | 4221 | TEST_GT (pid, 0); |
3682 | 4283 | 4222 | ||
3683 | 4284 | waitpid (pid, NULL, 0); | 4223 | waitpid (pid, NULL, 0); |
3684 | @@ -4319,7 +4258,7 @@ | |||
3685 | 4319 | class->console = CONSOLE_NONE; | 4258 | class->console = CONSOLE_NONE; |
3686 | 4320 | job = job_new (class, ""); | 4259 | job = job_new (class, ""); |
3687 | 4321 | 4260 | ||
3689 | 4322 | pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN); | 4261 | pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3690 | 4323 | TEST_GT (pid, 0); | 4262 | TEST_GT (pid, 0); |
3691 | 4324 | 4263 | ||
3692 | 4325 | waitpid (pid, NULL, 0); | 4264 | waitpid (pid, NULL, 0); |
3693 | @@ -4351,7 +4290,7 @@ | |||
3694 | 4351 | class->console = CONSOLE_LOG; | 4290 | class->console = CONSOLE_LOG; |
3695 | 4352 | job = job_new (class, ""); | 4291 | job = job_new (class, ""); |
3696 | 4353 | 4292 | ||
3698 | 4354 | pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN); | 4293 | pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3699 | 4355 | TEST_GT (pid, 0); | 4294 | TEST_GT (pid, 0); |
3700 | 4356 | 4295 | ||
3701 | 4357 | waitpid (pid, NULL, 0); | 4296 | waitpid (pid, NULL, 0); |
3702 | @@ -4398,7 +4337,7 @@ | |||
3703 | 4398 | class->chdir = "/tmp"; | 4337 | class->chdir = "/tmp"; |
3704 | 4399 | job = job_new (class, ""); | 4338 | job = job_new (class, ""); |
3705 | 4400 | 4339 | ||
3707 | 4401 | pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN); | 4340 | pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3708 | 4402 | TEST_GT (pid, 0); | 4341 | TEST_GT (pid, 0); |
3709 | 4403 | 4342 | ||
3710 | 4404 | waitpid (pid, NULL, 0); | 4343 | waitpid (pid, NULL, 0); |
3711 | @@ -4430,7 +4369,7 @@ | |||
3712 | 4430 | class->console = CONSOLE_NONE; | 4369 | class->console = CONSOLE_NONE; |
3713 | 4431 | job = job_new (class, ""); | 4370 | job = job_new (class, ""); |
3714 | 4432 | 4371 | ||
3716 | 4433 | pid = job_process_spawn (job, args, env, FALSE, -1, PROCESS_MAIN); | 4372 | pid = job_process_spawn_with_fd (job, args, env, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3717 | 4434 | TEST_GT (pid, 0); | 4373 | TEST_GT (pid, 0); |
3718 | 4435 | 4374 | ||
3719 | 4436 | waitpid (pid, NULL, 0); | 4375 | waitpid (pid, NULL, 0); |
3720 | @@ -4460,7 +4399,7 @@ | |||
3721 | 4460 | class->console = CONSOLE_NONE; | 4399 | class->console = CONSOLE_NONE; |
3722 | 4461 | job = job_new (class, ""); | 4400 | job = job_new (class, ""); |
3723 | 4462 | 4401 | ||
3725 | 4463 | pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN); | 4402 | pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3726 | 4464 | TEST_GT (pid, 0); | 4403 | TEST_GT (pid, 0); |
3727 | 4465 | 4404 | ||
3728 | 4466 | assert0 (waitid (P_PID, pid, &info, WEXITED | WSTOPPED | WCONTINUED)); | 4405 | assert0 (waitid (P_PID, pid, &info, WEXITED | WSTOPPED | WCONTINUED)); |
3729 | @@ -4483,7 +4422,7 @@ | |||
3730 | 4483 | class = job_class_new (NULL, "test", NULL); | 4422 | class = job_class_new (NULL, "test", NULL); |
3731 | 4484 | job = job_new (class, ""); | 4423 | job = job_new (class, ""); |
3732 | 4485 | class->console = CONSOLE_NONE; | 4424 | class->console = CONSOLE_NONE; |
3734 | 4486 | pid = job_process_spawn (job, args, NULL, TRUE, -1, PROCESS_MAIN); | 4425 | pid = job_process_spawn_with_fd (job, args, NULL, TRUE, -1, PROCESS_MAIN, &job_process_fd); |
3735 | 4487 | TEST_GT (pid, 0); | 4426 | TEST_GT (pid, 0); |
3736 | 4488 | 4427 | ||
3737 | 4489 | assert0 (waitid (P_PID, pid, &info, WEXITED | WSTOPPED | WCONTINUED)); | 4428 | assert0 (waitid (P_PID, pid, &info, WEXITED | WSTOPPED | WCONTINUED)); |
3738 | @@ -4516,8 +4455,12 @@ | |||
3739 | 4516 | class->console = CONSOLE_NONE; | 4455 | class->console = CONSOLE_NONE; |
3740 | 4517 | job = job_new (class, ""); | 4456 | job = job_new (class, ""); |
3741 | 4518 | 4457 | ||
3744 | 4519 | pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN); | 4458 | pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3745 | 4520 | TEST_LT (pid, 0); | 4459 | TEST_NE (pid, 0); |
3746 | 4460 | |||
3747 | 4461 | buffer = read_from_fd (NULL, job_process_fd); | ||
3748 | 4462 | TEST_NE_P (buffer, NULL); | ||
3749 | 4463 | job_process_error_handler (buffer->buf, buffer->len); | ||
3750 | 4521 | 4464 | ||
3751 | 4522 | err = nih_error_get (); | 4465 | err = nih_error_get (); |
3752 | 4523 | TEST_EQ (err->number, JOB_PROCESS_ERROR); | 4466 | TEST_EQ (err->number, JOB_PROCESS_ERROR); |
3753 | @@ -4528,6 +4471,7 @@ | |||
3754 | 4528 | TEST_EQ (perr->arg, 0); | 4471 | TEST_EQ (perr->arg, 0); |
3755 | 4529 | TEST_EQ (perr->errnum, ENOENT); | 4472 | TEST_EQ (perr->errnum, ENOENT); |
3756 | 4530 | nih_free (perr); | 4473 | nih_free (perr); |
3757 | 4474 | nih_free (buffer); | ||
3758 | 4531 | 4475 | ||
3759 | 4532 | /************************************************************/ | 4476 | /************************************************************/ |
3760 | 4533 | TEST_FEATURE ("with no such file, no shell and console log"); | 4477 | TEST_FEATURE ("with no such file, no shell and console log"); |
3761 | @@ -4539,29 +4483,36 @@ | |||
3762 | 4539 | class = job_class_new (NULL, "test", NULL); | 4483 | class = job_class_new (NULL, "test", NULL); |
3763 | 4540 | class->console = CONSOLE_LOG; | 4484 | class->console = CONSOLE_LOG; |
3764 | 4541 | job = job_new (class, ""); | 4485 | job = job_new (class, ""); |
3765 | 4486 | job->goal = JOB_START; | ||
3766 | 4487 | job->state = JOB_SPAWNED; | ||
3767 | 4542 | 4488 | ||
3768 | 4543 | TEST_NE_P (job->log, NULL); | 4489 | TEST_NE_P (job->log, NULL); |
3769 | 4544 | TEST_EQ_P (job->log[PROCESS_MAIN], NULL); | 4490 | TEST_EQ_P (job->log[PROCESS_MAIN], NULL); |
3772 | 4545 | pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN); | 4491 | pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3773 | 4546 | TEST_LT (pid, 0); | 4492 | job->process_data[PROCESS_MAIN] = NIH_MUST ( |
3774 | 4493 | job_process_data_new (job->process_data, job, PROCESS_MAIN, job_process_fd)); | ||
3775 | 4494 | TEST_WATCH_UPDATE (); | ||
3776 | 4495 | TEST_NE (pid, 0); | ||
3777 | 4547 | 4496 | ||
3778 | 4548 | TEST_GT (waitpid (-1, NULL, 0), 0); | 4497 | TEST_GT (waitpid (-1, NULL, 0), 0); |
3779 | 4549 | 4498 | ||
3780 | 4499 | NihIo *io = nih_io_reopen (job, job_process_fd, NIH_IO_STREAM, NULL, NULL, NULL, NULL); | ||
3781 | 4500 | TEST_NE_P (io, NULL); | ||
3782 | 4501 | buffer = read_from_fd (NULL, job_process_fd); | ||
3783 | 4502 | TEST_NE_P (buffer, NULL); | ||
3784 | 4503 | TEST_NE_P (job->process_data[PROCESS_MAIN], NULL); | ||
3785 | 4504 | TEST_TRUE (job->process_data[PROCESS_MAIN]->valid); | ||
3786 | 4505 | |||
3787 | 4506 | |||
3788 | 4507 | TEST_NE_P (job->log[PROCESS_MAIN], NULL); | ||
3789 | 4508 | |||
3790 | 4509 | job_process_child_reader (job->process_data[PROCESS_MAIN], io, buffer->buf, buffer->len); | ||
3791 | 4510 | |||
3792 | 4550 | /* The log should have been allocated in job_process_spawn, | 4511 | /* The log should have been allocated in job_process_spawn, |
3793 | 4551 | * but then freed on error. | 4512 | * but then freed on error. |
3794 | 4552 | */ | 4513 | */ |
3795 | 4553 | TEST_EQ_P (job->log[PROCESS_MAIN], NULL); | 4514 | TEST_EQ_P (job->log[PROCESS_MAIN], NULL); |
3796 | 4554 | 4515 | ||
3797 | 4555 | err = nih_error_get (); | ||
3798 | 4556 | TEST_EQ (err->number, JOB_PROCESS_ERROR); | ||
3799 | 4557 | TEST_ALLOC_SIZE (err, sizeof (JobProcessError)); | ||
3800 | 4558 | |||
3801 | 4559 | perr = (JobProcessError *)err; | ||
3802 | 4560 | TEST_EQ (perr->type, JOB_PROCESS_ERROR_EXEC); | ||
3803 | 4561 | TEST_EQ (perr->arg, 0); | ||
3804 | 4562 | TEST_EQ (perr->errnum, ENOENT); | ||
3805 | 4563 | nih_free (perr); | ||
3806 | 4564 | |||
3807 | 4565 | /* Check that we can spawn a job and pause it | 4516 | /* Check that we can spawn a job and pause it |
3808 | 4566 | */ | 4517 | */ |
3809 | 4567 | TEST_FEATURE ("with debug enabled"); | 4518 | TEST_FEATURE ("with debug enabled"); |
3810 | @@ -4577,7 +4528,7 @@ | |||
3811 | 4577 | args[1] = function; | 4528 | args[1] = function; |
3812 | 4578 | args[2] = NULL; | 4529 | args[2] = NULL; |
3813 | 4579 | 4530 | ||
3815 | 4580 | pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN); | 4531 | pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3816 | 4581 | TEST_GT (pid, 0); | 4532 | TEST_GT (pid, 0); |
3817 | 4582 | 4533 | ||
3818 | 4583 | /* Ensure process is still running after some period of time. | 4534 | /* Ensure process is still running after some period of time. |
3819 | @@ -4614,7 +4565,7 @@ | |||
3820 | 4614 | class->console = CONSOLE_NONE; | 4565 | class->console = CONSOLE_NONE; |
3821 | 4615 | job = job_new (class, ""); | 4566 | job = job_new (class, ""); |
3822 | 4616 | 4567 | ||
3824 | 4617 | pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN); | 4568 | pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3825 | 4618 | TEST_GT (pid, 0); | 4569 | TEST_GT (pid, 0); |
3826 | 4619 | 4570 | ||
3827 | 4620 | waitpid (pid, NULL, 0); | 4571 | waitpid (pid, NULL, 0); |
3828 | @@ -4669,7 +4620,7 @@ | |||
3829 | 4669 | class->console = CONSOLE_LOG; | 4620 | class->console = CONSOLE_LOG; |
3830 | 4670 | job = job_new (class, ""); | 4621 | job = job_new (class, ""); |
3831 | 4671 | 4622 | ||
3833 | 4672 | pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN); | 4623 | pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3834 | 4673 | TEST_GT (pid, 0); | 4624 | TEST_GT (pid, 0); |
3835 | 4674 | 4625 | ||
3836 | 4675 | waitpid (pid, NULL, 0); | 4626 | waitpid (pid, NULL, 0); |
3837 | @@ -4742,8 +4693,8 @@ | |||
3838 | 4742 | args[2] = filebuf; | 4693 | args[2] = filebuf; |
3839 | 4743 | args[3] = NULL; | 4694 | args[3] = NULL; |
3840 | 4744 | 4695 | ||
3843 | 4745 | job->pid[PROCESS_MAIN] = job_process_spawn (job, args, NULL, | 4696 | job->pid[PROCESS_MAIN] = job_process_spawn_with_fd (job, args, NULL, |
3844 | 4746 | FALSE, -1, PROCESS_MAIN); | 4697 | FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3845 | 4747 | pid = job->pid[PROCESS_MAIN]; | 4698 | pid = job->pid[PROCESS_MAIN]; |
3846 | 4748 | TEST_GT (pid, 0); | 4699 | TEST_GT (pid, 0); |
3847 | 4749 | 4700 | ||
3848 | @@ -4769,8 +4720,8 @@ | |||
3849 | 4769 | args[2] = filebuf; | 4720 | args[2] = filebuf; |
3850 | 4770 | args[3] = NULL; | 4721 | args[3] = NULL; |
3851 | 4771 | 4722 | ||
3854 | 4772 | job->pid[PROCESS_POST_START] = job_process_spawn (job, args, NULL, | 4723 | job->pid[PROCESS_POST_START] = job_process_spawn_with_fd (job, args, NULL, |
3855 | 4773 | FALSE, -1, PROCESS_POST_START); | 4724 | FALSE, -1, PROCESS_POST_START, &job_process_fd); |
3856 | 4774 | pid = job->pid[PROCESS_POST_START]; | 4725 | pid = job->pid[PROCESS_POST_START]; |
3857 | 4775 | TEST_GT (pid, 0); | 4726 | TEST_GT (pid, 0); |
3858 | 4776 | 4727 | ||
3859 | @@ -4867,7 +4818,7 @@ | |||
3860 | 4867 | NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, script)); | 4818 | NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, script)); |
3861 | 4868 | } | 4819 | } |
3862 | 4869 | 4820 | ||
3864 | 4870 | pid = job_process_spawn (job, args_array, NULL, FALSE, -1, PROCESS_MAIN); | 4821 | pid = job_process_spawn_with_fd (job, args_array, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3865 | 4871 | 4822 | ||
3866 | 4872 | if (test_alloc_failed) { | 4823 | if (test_alloc_failed) { |
3867 | 4873 | TEST_LT (pid, 0); | 4824 | TEST_LT (pid, 0); |
3868 | @@ -4934,7 +4885,7 @@ | |||
3869 | 4934 | NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, TEST_SHELL_ARG)); | 4885 | NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, TEST_SHELL_ARG)); |
3870 | 4935 | NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, script)); | 4886 | NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, script)); |
3871 | 4936 | 4887 | ||
3873 | 4937 | pid = job_process_spawn (job, args_array, NULL, FALSE, -1, PROCESS_MAIN); | 4888 | pid = job_process_spawn_with_fd (job, args_array, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3874 | 4938 | TEST_GT (pid, 0); | 4889 | TEST_GT (pid, 0); |
3875 | 4939 | 4890 | ||
3876 | 4940 | TEST_EQ (waitpid (pid, &status, 0), pid); | 4891 | TEST_EQ (waitpid (pid, &status, 0), pid); |
3877 | @@ -4990,7 +4941,7 @@ | |||
3878 | 4990 | NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, TEST_SHELL_ARG)); | 4941 | NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, TEST_SHELL_ARG)); |
3879 | 4991 | NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, script)); | 4942 | NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, script)); |
3880 | 4992 | 4943 | ||
3882 | 4993 | pid = job_process_spawn (job, args_array, NULL, FALSE, -1, PROCESS_MAIN); | 4944 | pid = job_process_spawn_with_fd (job, args_array, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3883 | 4994 | TEST_GT (pid, 0); | 4945 | TEST_GT (pid, 0); |
3884 | 4995 | 4946 | ||
3885 | 4996 | TEST_EQ (waitpid (pid, &status, 0), pid); | 4947 | TEST_EQ (waitpid (pid, &status, 0), pid); |
3886 | @@ -5043,7 +4994,7 @@ | |||
3887 | 5043 | NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, "-en")); | 4994 | NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, "-en")); |
3888 | 5044 | NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, "\\000")); | 4995 | NIH_MUST (nih_str_array_add (&args_array, NULL, &argc, "\\000")); |
3889 | 5045 | 4996 | ||
3891 | 5046 | pid = job_process_spawn (job, args_array, NULL, FALSE, -1, PROCESS_MAIN); | 4997 | pid = job_process_spawn_with_fd (job, args_array, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3892 | 5047 | TEST_GT (pid, 0); | 4998 | TEST_GT (pid, 0); |
3893 | 5048 | 4999 | ||
3894 | 5049 | TEST_EQ (waitpid (pid, &status, 0), pid); | 5000 | TEST_EQ (waitpid (pid, &status, 0), pid); |
3895 | @@ -5098,7 +5049,7 @@ | |||
3896 | 5098 | args[3] = filebuf; | 5049 | args[3] = filebuf; |
3897 | 5099 | args[4] = NULL; | 5050 | args[4] = NULL; |
3898 | 5100 | 5051 | ||
3900 | 5101 | pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN); | 5052 | pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3901 | 5102 | TEST_GT (pid, 0); | 5053 | TEST_GT (pid, 0); |
3902 | 5103 | 5054 | ||
3903 | 5104 | TEST_NE (waitpid (pid, &status, 0), -1); | 5055 | TEST_NE (waitpid (pid, &status, 0), -1); |
3904 | @@ -5161,7 +5112,7 @@ | |||
3905 | 5161 | args[3] = filebuf; | 5112 | args[3] = filebuf; |
3906 | 5162 | args[4] = NULL; | 5113 | args[4] = NULL; |
3907 | 5163 | 5114 | ||
3909 | 5164 | pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN); | 5115 | pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3910 | 5165 | TEST_GT (pid, 0); | 5116 | TEST_GT (pid, 0); |
3911 | 5166 | 5117 | ||
3912 | 5167 | TEST_WATCH_UPDATE (); | 5118 | TEST_WATCH_UPDATE (); |
3913 | @@ -5243,8 +5194,13 @@ | |||
3914 | 5243 | } | 5194 | } |
3915 | 5244 | } | 5195 | } |
3916 | 5245 | 5196 | ||
3919 | 5246 | pid = job_process_spawn (job, args, NULL, FALSE, -1, PROCESS_MAIN); | 5197 | pid = job_process_spawn_with_fd (job, args, NULL, FALSE, -1, PROCESS_MAIN, &job_process_fd); |
3920 | 5247 | TEST_LT (pid, 0); | 5198 | TEST_WATCH_UPDATE (); |
3921 | 5199 | TEST_NE (pid, 0); | ||
3922 | 5200 | |||
3923 | 5201 | buffer = read_from_fd (NULL, job_process_fd); | ||
3924 | 5202 | TEST_NE_P (buffer, NULL); | ||
3925 | 5203 | job_process_error_handler (buffer->buf, buffer->len); | ||
3926 | 5248 | 5204 | ||
3927 | 5249 | /* Ensure logging disabled in failure scenarios */ | 5205 | /* Ensure logging disabled in failure scenarios */ |
3928 | 5250 | TEST_EQ (class->console, CONSOLE_NONE); | 5206 | TEST_EQ (class->console, CONSOLE_NONE); |
3929 | @@ -5830,6 +5786,8 @@ | |||
3930 | 5830 | job->exit_status = 0; | 5786 | job->exit_status = 0; |
3931 | 5831 | 5787 | ||
3932 | 5832 | job_process_handler (NULL, 1, NIH_CHILD_EXITED, 0); | 5788 | job_process_handler (NULL, 1, NIH_CHILD_EXITED, 0); |
3933 | 5789 | TEST_EQ (job->state, JOB_SPAWNED); | ||
3934 | 5790 | job_change_state (job, job_next_state(job)); | ||
3935 | 5833 | 5791 | ||
3936 | 5834 | TEST_EQ (job->goal, JOB_START); | 5792 | TEST_EQ (job->goal, JOB_START); |
3937 | 5835 | TEST_EQ (job->state, JOB_RUNNING); | 5793 | TEST_EQ (job->state, JOB_RUNNING); |
3938 | @@ -9181,7 +9139,7 @@ | |||
3939 | 9181 | void | 9139 | void |
3940 | 9182 | run_tests (void) | 9140 | run_tests (void) |
3941 | 9183 | { | 9141 | { |
3943 | 9184 | test_run (); | 9142 | test_start (); |
3944 | 9185 | test_spawn (); | 9143 | test_spawn (); |
3945 | 9186 | test_log_path (); | 9144 | test_log_path (); |
3946 | 9187 | test_kill (); | 9145 | test_kill (); |
3947 | 9188 | 9146 | ||
3948 | === modified file 'init/tests/test_util.c' | |||
3949 | --- init/tests/test_util.c 2013-07-17 14:18:42 +0000 | |||
3950 | +++ init/tests/test_util.c 2014-05-22 13:31:23 +0000 | |||
3951 | @@ -1,5 +1,6 @@ | |||
3952 | 1 | #include "test_util_common.h" | ||
3953 | 2 | #undef PACKAGE_COPYRIGHT | ||
3954 | 1 | #include "test_util.h" | 3 | #include "test_util.h" |
3955 | 2 | #include "test_util_common.h" | ||
3956 | 3 | #include <nih/logging.h> | 4 | #include <nih/logging.h> |
3957 | 4 | #include <nih/test.h> | 5 | #include <nih/test.h> |
3958 | 5 | 6 | ||
3959 | 6 | 7 | ||
3960 | === modified file 'test/test_util_common.c' | |||
3961 | --- test/test_util_common.c 2014-04-11 21:15:39 +0000 | |||
3962 | +++ test/test_util_common.c 2014-05-22 13:31:23 +0000 | |||
3963 | @@ -28,6 +28,10 @@ | |||
3964 | 28 | #include <nih/string.h> | 28 | #include <nih/string.h> |
3965 | 29 | #include <nih/signal.h> | 29 | #include <nih/signal.h> |
3966 | 30 | #include <nih/logging.h> | 30 | #include <nih/logging.h> |
3967 | 31 | #include <nih/timer.h> | ||
3968 | 32 | #include <nih/io.h> | ||
3969 | 33 | #include <nih/child.h> | ||
3970 | 34 | #include <nih/main.h> | ||
3971 | 31 | #include <nih-dbus/test_dbus.h> | 35 | #include <nih-dbus/test_dbus.h> |
3972 | 32 | 36 | ||
3973 | 33 | #include <dbus/dbus.h> | 37 | #include <dbus/dbus.h> |
3974 | @@ -986,7 +990,7 @@ | |||
3975 | 986 | 990 | ||
3976 | 987 | /* Clean up if tests forgot to */ | 991 | /* Clean up if tests forgot to */ |
3977 | 988 | cmd = NIH_MUST (nih_sprintf (NULL, "rm %s/*.session 2>/dev/null", path)); | 992 | cmd = NIH_MUST (nih_sprintf (NULL, "rm %s/*.session 2>/dev/null", path)); |
3979 | 989 | system (cmd); | 993 | assert0 (system (cmd)); |
3980 | 990 | 994 | ||
3981 | 991 | /* Remove the directory tree the first Session Init created */ | 995 | /* Remove the directory tree the first Session Init created */ |
3982 | 992 | assert0 (rmdir (path)); | 996 | assert0 (rmdir (path)); |
3983 | @@ -1003,3 +1007,89 @@ | |||
3984 | 1003 | 1007 | ||
3985 | 1004 | } | 1008 | } |
3986 | 1005 | } | 1009 | } |
3987 | 1010 | |||
3988 | 1011 | /** | ||
3989 | 1012 | * timer_cb: | ||
3990 | 1013 | * | ||
3991 | 1014 | * @data: unused, | ||
3992 | 1015 | * @timer: timer. | ||
3993 | 1016 | * | ||
3994 | 1017 | * Exit main loop with an error value indicating that the expected main | ||
3995 | 1018 | * loop events/actions were not performed within the expected time. | ||
3996 | 1019 | **/ | ||
3997 | 1020 | void | ||
3998 | 1021 | timer_cb (void *data, NihTimer *timer) | ||
3999 | 1022 | { | ||
4000 | 1023 | nih_assert (timer); | ||
4001 | 1024 | |||
4002 | 1025 | /* Return non-zero to denote failure */ | ||
4003 | 1026 | nih_main_loop_exit (42); | ||
4004 | 1027 | } | ||
4005 | 1028 | |||
4006 | 1029 | /** | ||
4007 | 1030 | * fd_valid: | ||
4008 | 1031 | * @fd: file descriptor. | ||
4009 | 1032 | * | ||
4010 | 1033 | * Return 1 if @fd is valid, else 0. | ||
4011 | 1034 | **/ | ||
4012 | 1035 | int | ||
4013 | 1036 | fd_valid (int fd) | ||
4014 | 1037 | { | ||
4015 | 1038 | int flags = 0; | ||
4016 | 1039 | |||
4017 | 1040 | if (fd < 0) | ||
4018 | 1041 | return 0; | ||
4019 | 1042 | |||
4020 | 1043 | errno = 0; | ||
4021 | 1044 | flags = fcntl (fd, F_GETFL); | ||
4022 | 1045 | |||
4023 | 1046 | if (flags < 0) | ||
4024 | 1047 | return 0; | ||
4025 | 1048 | |||
4026 | 1049 | /* redundant really */ | ||
4027 | 1050 | if (errno == EBADF) | ||
4028 | 1051 | return 0; | ||
4029 | 1052 | |||
4030 | 1053 | return 1; | ||
4031 | 1054 | } | ||
4032 | 1055 | |||
4033 | 1056 | /** | ||
4034 | 1057 | * read_from_fd: | ||
4035 | 1058 | * | ||
4036 | 1059 | * @parent: parent, | ||
4037 | 1060 | * @fd: open file descriptor. | ||
4038 | 1061 | * | ||
4039 | 1062 | * Read from the specified fd, close the fd and return the data. | ||
4040 | 1063 | * | ||
4041 | 1064 | * Returns: Newly-allocated NihIoBuffer representing data read from @fd. | ||
4042 | 1065 | * | ||
4043 | 1066 | **/ | ||
4044 | 1067 | NihIoBuffer * | ||
4045 | 1068 | read_from_fd (void *parent, int fd) | ||
4046 | 1069 | { | ||
4047 | 1070 | NihIoBuffer *buffer = NULL; | ||
4048 | 1071 | ssize_t len; | ||
4049 | 1072 | |||
4050 | 1073 | assert (fd >= 0); | ||
4051 | 1074 | |||
4052 | 1075 | buffer = nih_io_buffer_new (parent); | ||
4053 | 1076 | nih_assert (buffer); | ||
4054 | 1077 | |||
4055 | 1078 | while (TRUE) { | ||
4056 | 1079 | |||
4057 | 1080 | nih_assert (! nih_io_buffer_resize (buffer, 1024)); | ||
4058 | 1081 | |||
4059 | 1082 | len = read (fd, | ||
4060 | 1083 | buffer->buf + buffer->len, | ||
4061 | 1084 | buffer->size - buffer->len); | ||
4062 | 1085 | |||
4063 | 1086 | if (len <= 0) | ||
4064 | 1087 | break; | ||
4065 | 1088 | else if (len > 0) | ||
4066 | 1089 | buffer->len += len; | ||
4067 | 1090 | } | ||
4068 | 1091 | |||
4069 | 1092 | close (fd); | ||
4070 | 1093 | |||
4071 | 1094 | return buffer; | ||
4072 | 1095 | } | ||
4073 | 1006 | 1096 | ||
4074 | === modified file 'test/test_util_common.h' | |||
4075 | --- test/test_util_common.h 2013-11-15 23:47:31 +0000 | |||
4076 | +++ test/test_util_common.h 2014-05-22 13:31:23 +0000 | |||
4077 | @@ -6,6 +6,10 @@ | |||
4078 | 6 | #include <sys/wait.h> | 6 | #include <sys/wait.h> |
4079 | 7 | 7 | ||
4080 | 8 | #include <nih-dbus/test_dbus.h> | 8 | #include <nih-dbus/test_dbus.h> |
4081 | 9 | #include <nih/timer.h> | ||
4082 | 10 | #include <nih/main.h> | ||
4083 | 11 | #include <nih/child.h> | ||
4084 | 12 | #include <nih/io.h> | ||
4085 | 9 | 13 | ||
4086 | 10 | /** | 14 | /** |
4087 | 11 | * TEST_DIR_MODE: | 15 | * TEST_DIR_MODE: |
4088 | @@ -34,6 +38,16 @@ | |||
4089 | 34 | 38 | ||
4090 | 35 | #define TEST_QUIESCE_TOTAL_WAIT_TIME (TEST_EXIT_TIME + TEST_QUIESCE_KILL_PHASE) | 39 | #define TEST_QUIESCE_TOTAL_WAIT_TIME (TEST_EXIT_TIME + TEST_QUIESCE_KILL_PHASE) |
4091 | 36 | 40 | ||
4092 | 41 | /** | ||
4093 | 42 | * TEST_MAIN_LOOP_TIMEOUT_SECS: | ||
4094 | 43 | * | ||
4095 | 44 | * Number of seconds to wait until the main loop is exited in error. | ||
4096 | 45 | * | ||
4097 | 46 | * To avoid a test failure, all main loops must exit within this | ||
4098 | 47 | * number of seconds. | ||
4099 | 48 | **/ | ||
4100 | 49 | #define TEST_MAIN_LOOP_TIMEOUT_SECS 5 | ||
4101 | 50 | |||
4102 | 37 | /* A 'reasonable' path, but which also contains a marker at the end so | 51 | /* A 'reasonable' path, but which also contains a marker at the end so |
4103 | 38 | * we know when we're looking at a PATH these tests have set. | 52 | * we know when we're looking at a PATH these tests have set. |
4104 | 39 | */ | 53 | */ |
4105 | @@ -74,6 +88,41 @@ | |||
4106 | 74 | } | 88 | } |
4107 | 75 | 89 | ||
4108 | 76 | /** | 90 | /** |
4109 | 91 | * TEST_WATCH_LOOP: | ||
4110 | 92 | * | ||
4111 | 93 | * Loop for NihIo object Updates, and process them until no watches | ||
4112 | 94 | * left. | ||
4113 | 95 | */ | ||
4114 | 96 | #define TEST_WATCH_LOOP() \ | ||
4115 | 97 | { \ | ||
4116 | 98 | /* Loop until we've fed all of the data. */ \ | ||
4117 | 99 | int first = TRUE; \ | ||
4118 | 100 | for (;;) { \ | ||
4119 | 101 | fd_set readfds, writefds, exceptfds; \ | ||
4120 | 102 | int nfds; \ | ||
4121 | 103 | \ | ||
4122 | 104 | nfds = 0; \ | ||
4123 | 105 | FD_ZERO (&readfds); \ | ||
4124 | 106 | FD_ZERO (&writefds); \ | ||
4125 | 107 | FD_ZERO (&exceptfds); \ | ||
4126 | 108 | \ | ||
4127 | 109 | nih_io_select_fds (&nfds, &readfds, \ | ||
4128 | 110 | &writefds, &exceptfds); \ | ||
4129 | 111 | if (! nfds) { \ | ||
4130 | 112 | if (first) \ | ||
4131 | 113 | TEST_FAILED ("expected to have " \ | ||
4132 | 114 | "data to feed."); \ | ||
4133 | 115 | break; \ | ||
4134 | 116 | } \ | ||
4135 | 117 | first = FALSE; \ | ||
4136 | 118 | \ | ||
4137 | 119 | select (nfds, &readfds, &writefds, &exceptfds, NULL); \ | ||
4138 | 120 | \ | ||
4139 | 121 | nih_io_handle_fds (&readfds, &writefds, &exceptfds); \ | ||
4140 | 122 | } \ | ||
4141 | 123 | } | ||
4142 | 124 | |||
4143 | 125 | /** | ||
4144 | 77 | * _TEST_WATCH_UPDATE: | 126 | * _TEST_WATCH_UPDATE: |
4145 | 78 | * @force: if TRUE, force an update, | 127 | * @force: if TRUE, force an update, |
4146 | 79 | * @timeout: struct timeval pointer, or NULL if no timeout required. | 128 | * @timeout: struct timeval pointer, or NULL if no timeout required. |
4147 | @@ -169,6 +218,30 @@ | |||
4148 | 169 | } | 218 | } |
4149 | 170 | 219 | ||
4150 | 171 | /** | 220 | /** |
4151 | 221 | * TEST_RESET_MAIN_LOOP: | ||
4152 | 222 | * | ||
4153 | 223 | * Reset main loop and associated test variables. | ||
4154 | 224 | **/ | ||
4155 | 225 | #define TEST_RESET_MAIN_LOOP() \ | ||
4156 | 226 | if (nih_main_loop_functions) { \ | ||
4157 | 227 | nih_free (nih_main_loop_functions); \ | ||
4158 | 228 | nih_main_loop_functions = NULL; \ | ||
4159 | 229 | } \ | ||
4160 | 230 | if (nih_child_watches) { \ | ||
4161 | 231 | nih_free (nih_child_watches); \ | ||
4162 | 232 | nih_child_watches = NULL; \ | ||
4163 | 233 | } \ | ||
4164 | 234 | if (nih_timers) { \ | ||
4165 | 235 | nih_free (nih_timers); \ | ||
4166 | 236 | nih_timers = NULL; \ | ||
4167 | 237 | } \ | ||
4168 | 238 | nih_child_init (); \ | ||
4169 | 239 | nih_main_loop_init (); \ | ||
4170 | 240 | nih_timer_init (); \ | ||
4171 | 241 | nih_io_init () | ||
4172 | 242 | |||
4173 | 243 | |||
4174 | 244 | /** | ||
4175 | 172 | * obj_string_check: | 245 | * obj_string_check: |
4176 | 173 | * | 246 | * |
4177 | 174 | * @a: first object, | 247 | * @a: first object, |
4178 | @@ -702,10 +775,10 @@ | |||
4179 | 702 | int string_check (const char *a, const char *b) | 775 | int string_check (const char *a, const char *b) |
4180 | 703 | __attribute__ ((warn_unused_result)); | 776 | __attribute__ ((warn_unused_result)); |
4181 | 704 | 777 | ||
4183 | 705 | const char * get_upstart_binary (void) | 778 | const char *get_upstart_binary (void) |
4184 | 706 | __attribute__ ((warn_unused_result)); | 779 | __attribute__ ((warn_unused_result)); |
4185 | 707 | 780 | ||
4187 | 708 | const char * get_initctl_binary (void) | 781 | const char *get_initctl_binary (void) |
4188 | 709 | __attribute__ ((warn_unused_result)); | 782 | __attribute__ ((warn_unused_result)); |
4189 | 710 | 783 | ||
4190 | 711 | int strcmp_compar (const void *a, const void *b) | 784 | int strcmp_compar (const void *a, const void *b) |
4191 | @@ -731,4 +804,17 @@ | |||
4192 | 731 | 804 | ||
4193 | 732 | void test_common_cleanup (void); | 805 | void test_common_cleanup (void); |
4194 | 733 | 806 | ||
4195 | 807 | void timer_cb (void *data, NihTimer *timer); | ||
4196 | 808 | |||
4197 | 809 | void test_job_process_handler (void *data, pid_t pid, | ||
4198 | 810 | NihChildEvents event, int status); | ||
4199 | 811 | |||
4200 | 812 | void test_main_loop_func (void *data, NihMainLoopFunc *self); | ||
4201 | 813 | |||
4202 | 814 | int fd_valid (int fd) | ||
4203 | 815 | __attribute__ ((warn_unused_result)); | ||
4204 | 816 | |||
4205 | 817 | NihIoBuffer *read_from_fd (void *parent, int fd) | ||
4206 | 818 | __attribute__ ((warn_unused_result)); | ||
4207 | 819 | |||
4208 | 734 | #endif /* TEST_UTIL_COMMON_H */ | 820 | #endif /* TEST_UTIL_COMMON_H */ |
4209 | 735 | 821 | ||
4210 | === modified file 'util/tests/test_initctl.c' | |||
4211 | --- util/tests/test_initctl.c 2014-05-07 19:08:35 +0000 | |||
4212 | +++ util/tests/test_initctl.c 2014-05-22 13:31:23 +0000 | |||
4213 | @@ -11535,7 +11535,7 @@ | |||
4214 | 11535 | TEST_NE_P (sessiondir, NULL); | 11535 | TEST_NE_P (sessiondir, NULL); |
4215 | 11536 | 11536 | ||
4216 | 11537 | cmd = nih_sprintf (NULL, "rm %s/upstart/sessions/*.session 2>/dev/null", sessiondir); | 11537 | cmd = nih_sprintf (NULL, "rm %s/upstart/sessions/*.session 2>/dev/null", sessiondir); |
4218 | 11538 | system (cmd); | 11538 | assert0 (system (cmd)); |
4219 | 11539 | 11539 | ||
4220 | 11540 | /* Use the "secret" interface */ | 11540 | /* Use the "secret" interface */ |
4221 | 11541 | TEST_EQ (setenv ("UPSTART_CONFDIR", confdir, 1), 0); | 11541 | TEST_EQ (setenv ("UPSTART_CONFDIR", confdir, 1), 0); |