Merge lp:~vorlon/upstart/stateful-reexec-confsource into lp:~upstart-devel/upstart/stateful-reexec
- stateful-reexec-confsource
- Merge into stateful-reexec
Proposed by
Steve Langasek
Status: | Merged |
---|---|
Merged at revision: | 1438 |
Proposed branch: | lp:~vorlon/upstart/stateful-reexec-confsource |
Merge into: | lp:~upstart-devel/upstart/stateful-reexec |
Diff against target: |
1469 lines (+401/-596) 8 files modified
init/event.c (+29/-35) init/job.c (+148/-223) init/job_class.c (+133/-212) init/log.c (+43/-37) init/log.h (+1/-1) init/process.c (+12/-32) init/session.c (+35/-39) init/state.h (+0/-17) |
To merge this branch: | bzr merge lp:~vorlon/upstart/stateful-reexec-confsource |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Hunt | Pending | ||
Review via email: mp+123517@code.launchpad.net |
Commit message
Description of the change
(Targeting the new branch)
Simplify the serialization/
To post a comment you must log in.
- 1447. By Steve Langasek
-
Resync with the main branch
- 1448. By Steve Langasek
-
adjust comments to reflect the code that's changed
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'init/event.c' |
2 | --- init/event.c 2012-09-10 02:52:58 +0000 |
3 | +++ init/event.c 2012-09-11 00:41:20 +0000 |
4 | @@ -629,20 +629,22 @@ |
5 | * event_deserialise: |
6 | * @json: JSON-serialised Event object to deserialise. |
7 | * |
8 | - * Convert @json into a partial Event object. |
9 | + * Convert @json into an Event object. |
10 | * |
11 | * Note that the object returned is not a true Event since not all |
12 | * structure elements are encoded in the JSON. Of particular note are |
13 | * that event->blocking and event->blockers are handled by |
14 | * state_serialise_resolve_deps(). |
15 | * |
16 | - * Returns: partial Event object, or NULL on error. |
17 | + * Returns: Event object, or NULL on error. |
18 | **/ |
19 | static Event * |
20 | event_deserialise (json_object *json) |
21 | { |
22 | json_object *json_env; |
23 | - Event *partial; |
24 | + Event *event; |
25 | + nih_local char *name; |
26 | + char **env; |
27 | int session_index; |
28 | |
29 | nih_assert (json); |
30 | @@ -650,43 +652,41 @@ |
31 | if (! state_check_json_type (json, object)) |
32 | return NULL; |
33 | |
34 | - partial = nih_new (NULL, Event); |
35 | - if (! partial) |
36 | + if (! state_get_json_string_var (json, "name", NULL, name)) |
37 | + goto error; |
38 | + |
39 | + if (! state_get_json_var_full (json, "env", array, json_env)) |
40 | + goto error; |
41 | + |
42 | + env = state_deserialise_str_array (NULL, json_env, TRUE); |
43 | + if (! env) |
44 | + goto error; |
45 | + |
46 | + event = event_new (NULL, name, env); |
47 | + if (! event) |
48 | return NULL; |
49 | |
50 | - memset (partial, '\0', sizeof (Event)); |
51 | - |
52 | - if (! state_get_json_string_var_to_obj (json, partial, name)) |
53 | - goto error; |
54 | - |
55 | - if (! state_get_json_int_var_to_obj (json, partial, fd)) |
56 | + if (! state_get_json_int_var_to_obj (json, event, fd)) |
57 | goto error; |
58 | |
59 | if (! state_get_json_int_var (json, "session", session_index)) |
60 | goto error; |
61 | |
62 | /* can't check return value here (as all values are legitimate) */ |
63 | - partial->session = session_from_index (session_index); |
64 | - |
65 | - if (! state_get_json_var_full (json, "env", array, json_env)) |
66 | - goto error; |
67 | - |
68 | - partial->env = state_deserialise_str_array (partial, json_env, TRUE); |
69 | - if (! partial->env) |
70 | - goto error; |
71 | + event->session = session_from_index (session_index); |
72 | |
73 | if (! state_get_json_enum_var (json, |
74 | event_progress_str_to_enum, |
75 | - "progress", partial->progress)) |
76 | - goto error; |
77 | - |
78 | - if (! state_set_json_int_var_from_obj (json, partial, failed)) |
79 | - goto error; |
80 | - |
81 | - return partial; |
82 | + "progress", event->progress)) |
83 | + goto error; |
84 | + |
85 | + if (! state_set_json_int_var_from_obj (json, event, failed)) |
86 | + goto error; |
87 | + |
88 | + return event; |
89 | |
90 | error: |
91 | - nih_free (partial); |
92 | + nih_free (event); |
93 | return NULL; |
94 | } |
95 | |
96 | @@ -702,7 +702,6 @@ |
97 | int |
98 | event_deserialise_all (json_object *json) |
99 | { |
100 | - nih_local Event *partial = NULL; |
101 | Event *event; |
102 | |
103 | nih_assert (json); |
104 | @@ -728,14 +727,9 @@ |
105 | if (! state_check_json_type (json_event, object)) |
106 | goto error; |
107 | |
108 | - partial = event_deserialise (json_event); |
109 | - if (! partial) |
110 | + event = event_deserialise (json_event); |
111 | + if (! event) |
112 | goto error; |
113 | - |
114 | - /* Create a new event */ |
115 | - event = NIH_MUST (event_new (NULL, partial->name, partial->env)); |
116 | - |
117 | - event->session = partial->session; |
118 | } |
119 | |
120 | return 0; |
121 | |
122 | === modified file 'init/job.c' |
123 | --- init/job.c 2012-09-10 05:24:47 +0000 |
124 | +++ init/job.c 2012-09-11 00:41:20 +0000 |
125 | @@ -63,7 +63,7 @@ |
126 | |
127 | /* Prototypes for static functions */ |
128 | static json_object *job_serialise (const Job *job); |
129 | -static Job *job_deserialise (json_object *json); |
130 | +static Job *job_deserialise (JobClass *parent, json_object *json); |
131 | |
132 | static const char * |
133 | job_goal_enum_to_str (JobGoal goal) |
134 | @@ -93,7 +93,7 @@ |
135 | __attribute__ ((malloc, warn_unused_result)); |
136 | |
137 | static NihTimer * |
138 | -job_deserialise_kill_timer (void *parent, json_object *json) |
139 | +job_deserialise_kill_timer (json_object *json) |
140 | __attribute__ ((malloc, warn_unused_result)); |
141 | |
142 | /** |
143 | @@ -155,6 +155,7 @@ |
144 | job->stop_env = NULL; |
145 | |
146 | job->stop_on = NULL; |
147 | + |
148 | if (class->stop_on) { |
149 | job->stop_on = event_operator_copy (job, class->stop_on); |
150 | if (! job->stop_on) |
151 | @@ -1699,7 +1700,7 @@ |
152 | json_logs = json_object_new_array (); |
153 | |
154 | if (! json_logs) |
155 | - goto error; |
156 | + return json; |
157 | |
158 | for (int process = 0; process < PROCESS_LAST; process++) { |
159 | json_object *json_log; |
160 | @@ -1731,6 +1732,7 @@ |
161 | json_object * |
162 | job_serialise_all (const NihHash *jobs) |
163 | { |
164 | + int count = 0; |
165 | json_object *json; |
166 | |
167 | nih_assert (jobs); |
168 | @@ -1743,6 +1745,7 @@ |
169 | json_object *json_job; |
170 | Job *job = (Job *)iter; |
171 | |
172 | + count++; |
173 | json_job = job_serialise (job); |
174 | |
175 | if (! json_job) |
176 | @@ -1751,6 +1754,12 @@ |
177 | json_object_array_add (json, json_job); |
178 | } |
179 | |
180 | + /* Raise an error to avoid serialising job classes with |
181 | + * no associated jobs. |
182 | + */ |
183 | + if (!count) |
184 | + goto error; |
185 | + |
186 | return json; |
187 | |
188 | error: |
189 | @@ -1760,58 +1769,60 @@ |
190 | |
191 | /** |
192 | * job_deserialise: |
193 | + * @parent: job class for JSON-encoded jobs, |
194 | * @json: JSON-serialised Job object to deserialise. |
195 | * |
196 | - * Note that the object returned is not a true Job since not all |
197 | - * structure elements are encoded in the JSON. Of particular note are |
198 | - * that job->blocking is handled by state_serialise_resolve_deps(). |
199 | - * |
200 | * XXX: All events must have been deserialised prior to this function |
201 | * XXX: being called. |
202 | * |
203 | - * Returns: partial Job object, or NULL on error. |
204 | + * Returns: Job object, or NULL on error. |
205 | **/ |
206 | static Job * |
207 | -job_deserialise (json_object *json) |
208 | +job_deserialise (JobClass *parent, json_object *json) |
209 | { |
210 | - Job *partial; |
211 | - json_object *kill_timer; |
212 | - json_object *blocker; |
213 | + nih_local char *name = NULL; |
214 | + Job *job; |
215 | + json_object *json_kill_timer; |
216 | + json_object *blocker; |
217 | + json_object *json_fds; |
218 | + json_object *json_pid; |
219 | + json_object *json_logs; |
220 | + size_t len; |
221 | + int ret; |
222 | |
223 | nih_assert (json); |
224 | |
225 | if (! state_check_json_type (json, object)) |
226 | return NULL; |
227 | |
228 | - partial = nih_new (NULL, Job); |
229 | - if (! partial) |
230 | + if (! state_get_json_string_var (json, "name", NULL, name)) |
231 | + goto error; |
232 | + |
233 | + job = NIH_MUST (job_new (parent, name)); |
234 | + |
235 | + if (! job) |
236 | return NULL; |
237 | |
238 | - memset (partial, '\0', sizeof (Job)); |
239 | - |
240 | - if (! state_get_json_string_var_to_obj (json, partial, name)) |
241 | - goto error; |
242 | - |
243 | - if (! state_get_json_string_var_to_obj (json, partial, path)) |
244 | + if (! state_get_json_string_var_to_obj (json, job, path)) |
245 | goto error; |
246 | |
247 | if (! state_get_json_enum_var (json, |
248 | job_goal_str_to_enum, |
249 | - "goal", partial->goal)) |
250 | + "goal", job->goal)) |
251 | goto error; |
252 | |
253 | if (! state_get_json_enum_var (json, |
254 | job_state_str_to_enum, |
255 | - "state", partial->state)) |
256 | - goto error; |
257 | - |
258 | - if (! state_get_json_env_array_to_obj (json, partial, env)) |
259 | - goto error; |
260 | - |
261 | - if (! state_get_json_env_array_to_obj (json, partial, start_env)) |
262 | - goto error; |
263 | - |
264 | - if (! state_get_json_env_array_to_obj (json, partial, stop_env)) |
265 | + "state", job->state)) |
266 | + goto error; |
267 | + |
268 | + if (! state_get_json_env_array_to_obj (json, job, env)) |
269 | + goto error; |
270 | + |
271 | + if (! state_get_json_env_array_to_obj (json, job, start_env)) |
272 | + goto error; |
273 | + |
274 | + if (! state_get_json_env_array_to_obj (json, job, stop_env)) |
275 | goto error; |
276 | |
277 | if (json_object_object_get (json, "stop_on")) { |
278 | @@ -1841,8 +1852,9 @@ |
279 | goto error; |
280 | } |
281 | |
282 | - partial->stop_on = event_operator_copy (partial, tmp->stop_on); |
283 | - if (! partial->stop_on) |
284 | + nih_free (job->stop_on); |
285 | + job->stop_on = event_operator_copy (job, tmp->stop_on); |
286 | + if (! job->stop_on) |
287 | goto error; |
288 | } |
289 | } |
290 | @@ -1859,63 +1871,122 @@ |
291 | |
292 | if (! state_get_json_int_var (json, "blocker", event_index)) |
293 | goto error; |
294 | - partial->blocker = event_from_index (event_index); |
295 | + job->blocker = event_from_index (event_index); |
296 | |
297 | - if (! partial->blocker) |
298 | + if (! job->blocker) |
299 | goto error; |
300 | } |
301 | |
302 | + if (! state_get_json_enum_var (json, |
303 | + process_type_str_to_enum, |
304 | + "kill_process", job->kill_process)) |
305 | + goto error; |
306 | + |
307 | /* FIXME: kill_timer */ |
308 | nih_info ("XXX: WARNING (%s:%d) job->kill_timer needs testing", __func__, __LINE__); |
309 | /* Check to see if a kill timer exists first since we do not |
310 | * want to end up creating a real but empty timer. |
311 | */ |
312 | - kill_timer = json_object_object_get (json, "kill_timer"); |
313 | + json_kill_timer = json_object_object_get (json, "kill_timer"); |
314 | |
315 | - if (kill_timer) { |
316 | - partial->kill_timer = job_deserialise_kill_timer (partial, json); |
317 | - if (! partial->kill_timer) |
318 | + if (json_kill_timer) { |
319 | + /* Found a partial kill timer, so create a new one and |
320 | + * adjust its due time. By the time the main loop gets |
321 | + * called, the due time will probably be in the past |
322 | + * such that the job will be stopped. |
323 | + * |
324 | + * To be completely fair we should: |
325 | + * |
326 | + * - encode the time at the point of serialisation in a |
327 | + * JSON 'meta' header. |
328 | + * - query the time post-deserialisation and calculate |
329 | + * the delta (being the time to perform the stateful |
330 | + * re-exec). |
331 | + * - add that time to all jobs with active kill timers |
332 | + * to give their processes the full amount of time to |
333 | + * end. |
334 | + */ |
335 | + nih_local NihTimer *kill_timer = job_deserialise_kill_timer (json_kill_timer); |
336 | + if (! kill_timer) |
337 | goto error; |
338 | - } else { |
339 | - partial->kill_timer = NULL; |
340 | + |
341 | + nih_assert (job->kill_process); |
342 | + job_process_set_kill_timer (job, job->kill_process, |
343 | + kill_timer->timeout); |
344 | + job_process_adj_kill_timer (job, kill_timer->due); |
345 | } |
346 | |
347 | - if (! state_get_json_enum_var (json, |
348 | - process_type_str_to_enum, |
349 | - "kill_process", partial->kill_process)) |
350 | - goto error; |
351 | - |
352 | - if (! state_get_json_int_var_to_obj (json, partial, failed)) |
353 | - goto error; |
354 | - |
355 | - if (! state_get_json_enum_var (json, |
356 | - process_type_str_to_enum, |
357 | - "failed_process", partial->failed_process)) |
358 | - goto error; |
359 | - |
360 | - if (! state_get_json_int_var_to_obj (json, partial, exit_status)) |
361 | - goto error; |
362 | - |
363 | - if (! state_get_json_int_var_to_obj (json, partial, respawn_time)) |
364 | - goto error; |
365 | - |
366 | - if (! state_get_json_int_var_to_obj (json, partial, respawn_count)) |
367 | - goto error; |
368 | - |
369 | - if (! state_get_json_int_var_to_obj (json, partial, trace_forks)) |
370 | + if (! state_get_json_int_var_to_obj (json, job, failed)) |
371 | + goto error; |
372 | + |
373 | + if (! state_get_json_enum_var (json, |
374 | + process_type_str_to_enum, |
375 | + "failed_process", job->failed_process)) |
376 | + goto error; |
377 | + |
378 | + if (! state_get_json_int_var_to_obj (json, job, exit_status)) |
379 | + goto error; |
380 | + |
381 | + if (! state_get_json_int_var_to_obj (json, job, respawn_time)) |
382 | + goto error; |
383 | + |
384 | + if (! state_get_json_int_var_to_obj (json, job, respawn_count)) |
385 | + goto error; |
386 | + |
387 | + json_fds = json_object_object_get (json, "fds"); |
388 | + if (! json_fds) |
389 | + goto error; |
390 | + |
391 | + ret = state_deserialise_int_array (job, json_fds, |
392 | + int, &job->fds, &job->num_fds); |
393 | + if (ret < 0) |
394 | + goto error; |
395 | + |
396 | + json_pid = json_object_object_get (json, "pid"); |
397 | + if (! json_pid) |
398 | + goto error; |
399 | + |
400 | + ret = state_deserialise_int_array (job, json_pid, |
401 | + pid_t, &job->pid, &len); |
402 | + if (ret < 0) |
403 | + goto error; |
404 | + |
405 | + if (len != PROCESS_LAST) |
406 | + goto error; |
407 | + |
408 | + if (! state_get_json_int_var_to_obj (json, job, trace_forks)) |
409 | goto error; |
410 | |
411 | if (! state_get_json_enum_var (json, |
412 | job_trace_state_str_to_enum, |
413 | - "trace_state", partial->trace_state)) |
414 | - goto error; |
415 | - |
416 | - /* log handled by caller */ |
417 | - |
418 | - return partial; |
419 | + "trace_state", job->trace_state)) |
420 | + goto error; |
421 | + |
422 | + json_logs = json_object_object_get (json, "log"); |
423 | + |
424 | + if (! json_logs) |
425 | + goto error; |
426 | + |
427 | + if (! state_check_json_type (json_logs, array)) |
428 | + goto error; |
429 | + |
430 | + for (int process = 0; process < PROCESS_LAST; process++) { |
431 | + json_object *json_log; |
432 | + |
433 | + json_log = json_object_array_get_idx (json_logs, process); |
434 | + if (! json_log) |
435 | + goto error; |
436 | + |
437 | + /* NULL if there was no log configured, or we failed to |
438 | + * deserialise it; either way, this should be non-fatal. |
439 | + */ |
440 | + job->log[process] = log_deserialise (job->log, json_log); |
441 | + } |
442 | + |
443 | + return job; |
444 | |
445 | error: |
446 | - nih_free (partial); |
447 | + nih_free (job); |
448 | return NULL; |
449 | } |
450 | |
451 | @@ -1934,12 +2005,7 @@ |
452 | job_deserialise_all (JobClass *parent, json_object *json) |
453 | { |
454 | json_object *json_jobs; |
455 | - json_object *json_fds; |
456 | - json_object *json_pid; |
457 | - json_object *json_logs; |
458 | Job *job; |
459 | - size_t len; |
460 | - int ret; |
461 | |
462 | nih_assert (parent); |
463 | nih_assert (json); |
464 | @@ -1954,8 +2020,6 @@ |
465 | |
466 | for (int i = 0; i < json_object_array_length (json_jobs); i++) { |
467 | json_object *json_job; |
468 | - nih_local Job *partial = NULL; |
469 | - Log *partial_log = NULL; |
470 | |
471 | json_job = json_object_array_get_idx (json_jobs, i); |
472 | if (! json_job) |
473 | @@ -1964,147 +2028,10 @@ |
474 | if (! state_check_json_type (json_job, object)) |
475 | goto error; |
476 | |
477 | - partial = job_deserialise (json_job); |
478 | - if (! partial) |
479 | - goto error; |
480 | - |
481 | - job = NIH_MUST (job_new (parent, partial->name)); |
482 | - |
483 | - state_partial_copy_int (job, partial, goal); |
484 | - state_partial_copy_int (job, partial, state); |
485 | - |
486 | - if (! state_copy_str_array_to_obj (job, partial, env)) |
487 | - goto error; |
488 | - |
489 | - if (! state_copy_str_array_to_obj (job, partial, start_env)) |
490 | - goto error; |
491 | - if (! state_copy_str_array_to_obj (job, partial, stop_env)) |
492 | - goto error; |
493 | - |
494 | - if (! state_copy_event_oper_to_obj (job, partial, stop_on)) |
495 | - goto error; |
496 | - |
497 | - json_fds = json_object_object_get (json_job, "fds"); |
498 | - if (! json_fds) |
499 | - goto error; |
500 | - |
501 | - ret = state_deserialise_int_array (job, json_fds, |
502 | - int, &job->fds, &job->num_fds); |
503 | - if (ret < 0) |
504 | - goto error; |
505 | - |
506 | - json_pid = json_object_object_get (json_job, "pid"); |
507 | - if (! json_pid) |
508 | - goto error; |
509 | - |
510 | - ret = state_deserialise_int_array (job, json_pid, |
511 | - pid_t, &job->pid, &len); |
512 | - if (ret < 0) |
513 | - goto error; |
514 | - |
515 | - if (len != PROCESS_LAST) |
516 | - goto error; |
517 | - |
518 | - state_partial_copy_ptr (job, partial, blocker); |
519 | - |
520 | - /* 'blocking' handled by state_deserialise_blocking() */ |
521 | - |
522 | - state_partial_copy_int (job, partial, kill_process); |
523 | - |
524 | - /* Found a partial kill timer, so create a new one and |
525 | - * adjust its due time. By the time the main loop gets |
526 | - * called, the due time will probably be in the past |
527 | - * such that the job will be stopped. |
528 | - * |
529 | - * To be completely fair we should: |
530 | - * |
531 | - * - encode the time at the point of serialisation in a |
532 | - * JSON 'meta' header. |
533 | - * - query the time post-deserialisation and calculate |
534 | - * the delta (being the time to perform the stateful |
535 | - * re-exec). |
536 | - * - add that time to all jobs with active kill timers |
537 | - * to give their processes the full amount of time to |
538 | - * end. |
539 | - */ |
540 | - if (partial->kill_timer) { |
541 | - nih_assert (job->kill_process); |
542 | - job_process_set_kill_timer (job, |
543 | - job->kill_process, |
544 | - partial->kill_timer->timeout); |
545 | - job_process_adj_kill_timer (job, |
546 | - partial->kill_timer->due); |
547 | - } |
548 | - |
549 | - state_partial_copy_int (job, partial, failed); |
550 | - state_partial_copy_int (job, partial, failed_process); |
551 | - state_partial_copy_int (job, partial, exit_status); |
552 | - state_partial_copy_int (job, partial, respawn_time); |
553 | - state_partial_copy_int (job, partial, respawn_count); |
554 | - state_partial_copy_int (job, partial, trace_forks); |
555 | - state_partial_copy_int (job, partial, trace_state); |
556 | - |
557 | - /* FIXME: handle ptraced jobs across re-exec */ |
558 | - if (partial->trace_state != TRACE_NONE) { |
559 | - nih_info ("XXX: WARNING (%s:%d) tracking of ptraced job instance '%s' (class '%s') will now stop", |
560 | - __func__, __LINE__, |
561 | - job->name ? job->name : "", |
562 | - job->class->name); |
563 | - } |
564 | - |
565 | - json_logs = json_object_object_get (json_job, "log"); |
566 | - |
567 | - if (! json_logs) |
568 | - continue; |
569 | - |
570 | - if (! state_check_json_type (json_logs, array)) |
571 | - goto error; |
572 | - |
573 | - for (int process = 0; process < PROCESS_LAST; process++) { |
574 | - json_object *json_log; |
575 | - int io_watch_fd = -1; |
576 | - |
577 | - json_log = json_object_array_get_idx (json_logs, process); |
578 | - if (! json_log) |
579 | - goto error; |
580 | - |
581 | - partial_log = log_deserialise (json_log); |
582 | - if (! partial_log) |
583 | - goto error; |
584 | - |
585 | - if (! *partial_log->path) { |
586 | - /* This log object was simply a |
587 | - * placeholder so don't apply it. |
588 | - */ |
589 | - nih_free (partial_log); |
590 | - job->log[process] = NULL; |
591 | - continue; |
592 | - } |
593 | - |
594 | - if (! state_get_json_int_var (json_log, "io_watch_fd", io_watch_fd)) |
595 | - goto error; |
596 | - |
597 | - /* re-apply CLOEXEC flag to stop fd being leaked to children */ |
598 | - if (io_watch_fd != -1 && state_toggle_cloexec (io_watch_fd, TRUE) < 0) |
599 | - goto error; |
600 | - |
601 | - job->log[process] = log_new (job->log, partial_log->path, io_watch_fd, partial_log->uid); |
602 | - if (! job->log[process]) |
603 | - goto error; |
604 | - |
605 | - state_partial_copy_int (job->log[process], partial_log, fd); |
606 | - state_partial_copy_int (job->log[process], partial_log, detached); |
607 | - state_partial_copy_int (job->log[process], partial_log, remote_closed); |
608 | - state_partial_copy_int (job->log[process], partial_log, open_errno); |
609 | - |
610 | - if (partial_log->unflushed->len) { |
611 | - ret = nih_io_buffer_push (job->log[process]->unflushed, |
612 | - partial_log->unflushed->buf, |
613 | - partial_log->unflushed->len); |
614 | - if (ret < 0) |
615 | - goto error; |
616 | - } |
617 | - } |
618 | + job = job_deserialise (parent, json_job); |
619 | + if (! job) |
620 | + goto error; |
621 | + |
622 | } |
623 | |
624 | return 0; |
625 | @@ -2279,7 +2206,6 @@ |
626 | /** |
627 | * job_deserialise_kill_timer: |
628 | * |
629 | - * @parent: parent for timer. |
630 | * @json: JSON representation of NihTimer. |
631 | * |
632 | * Deserialise @json back into an NihTimer. |
633 | @@ -2287,14 +2213,13 @@ |
634 | * Returns: NihTimer on NULL on error. |
635 | **/ |
636 | static NihTimer * |
637 | -job_deserialise_kill_timer (void *parent, json_object *json) |
638 | +job_deserialise_kill_timer (json_object *json) |
639 | { |
640 | NihTimer *timer; |
641 | |
642 | - nih_assert (parent); |
643 | nih_assert (json); |
644 | |
645 | - timer = nih_new (parent, NihTimer); |
646 | + timer = nih_new (NULL, NihTimer); |
647 | if (! timer) |
648 | return NULL; |
649 | |
650 | |
651 | === modified file 'init/job_class.c' |
652 | --- init/job_class.c 2012-09-10 07:43:23 +0000 |
653 | +++ init/job_class.c 2012-09-11 00:41:20 +0000 |
654 | @@ -1795,38 +1795,34 @@ |
655 | |
656 | json_class = job_class_serialise (class); |
657 | |
658 | + /* No object returned means the class doesn't need to be |
659 | + * serialised. Even if this is a real failure, it's always |
660 | + * better to serialise as much of the state as possible. |
661 | + */ |
662 | if (! json_class) |
663 | - goto error; |
664 | + continue; |
665 | |
666 | json_object_array_add (json, json_class); |
667 | } |
668 | |
669 | return json; |
670 | - |
671 | -error: |
672 | - json_object_put (json); |
673 | - return NULL; |
674 | } |
675 | |
676 | /** |
677 | * job_class_deserialise: |
678 | * @json: JSON-serialised JobClass object to deserialise. |
679 | * |
680 | - * Note that the object returned is not a true JobClass since not all |
681 | - * structure elements are encoded in the JSON. |
682 | - * |
683 | - * Further, note that limits, process, instances (jobs), and normalexit |
684 | - * are NOT handled by this function - use state_rlimit_deserialise_all(), |
685 | - * process_deserialise_all(), job_deserialise_all() and |
686 | - * state_deserialise_int_array() respectively. |
687 | - * |
688 | - * Returns: partial JobClass object, or NULL on error. |
689 | + * Returns: JobClass object, or NULL on error. |
690 | **/ |
691 | static JobClass * |
692 | job_class_deserialise (json_object *json) |
693 | { |
694 | - JobClass *partial; |
695 | + json_object *json_normalexit; |
696 | + JobClass *class = NULL; |
697 | int session_index; |
698 | + int ret; |
699 | + nih_local char *name = NULL; |
700 | + nih_local char *path = NULL; |
701 | |
702 | nih_assert (json); |
703 | nih_assert (job_classes); |
704 | @@ -1834,47 +1830,47 @@ |
705 | if (! state_check_json_type (json, object)) |
706 | goto error; |
707 | |
708 | - partial = nih_new (NULL, JobClass); |
709 | - if (! partial) |
710 | - return NULL; |
711 | - |
712 | - memset (partial, '\0', sizeof (JobClass)); |
713 | - |
714 | - if (! state_get_json_string_var_to_obj (json, partial, name)) |
715 | - goto error; |
716 | - |
717 | - if (! state_get_json_string_var_to_obj (json, partial, path)) |
718 | - goto error; |
719 | - |
720 | if (! state_get_json_int_var (json, "session", session_index)) |
721 | - goto error; |
722 | - |
723 | - /* can't check return value here (as all values are legitimate) */ |
724 | - partial->session = session_from_index (session_index); |
725 | - |
726 | - if (partial->session != NULL) { |
727 | + goto error; |
728 | + |
729 | + if (! state_get_json_string_var (json, "name", NULL, name)) |
730 | + goto error; |
731 | + |
732 | + class = NIH_MUST (job_class_new (NULL, name, |
733 | + session_from_index (session_index))); |
734 | + if (! class) |
735 | + goto error; |
736 | + |
737 | + if (class->session != NULL) { |
738 | nih_warn ("XXX: WARNING (%s:%d): deserialisation of " |
739 | "user jobs and chroot sessions not currently supported", |
740 | __func__, __LINE__); |
741 | goto error; |
742 | } |
743 | |
744 | - if (! state_get_json_string_var_to_obj (json, partial, instance)) |
745 | - goto error; |
746 | - |
747 | - if (! state_get_json_string_var_to_obj (json, partial, description)) |
748 | - goto error; |
749 | - |
750 | - if (! state_get_json_string_var_to_obj (json, partial, author)) |
751 | - goto error; |
752 | - |
753 | - if (! state_get_json_string_var_to_obj (json, partial, version)) |
754 | - goto error; |
755 | - |
756 | - if (! state_get_json_env_array_to_obj (json, partial, env)) |
757 | - goto error; |
758 | - |
759 | - if (! state_get_json_env_array_to_obj (json, partial, export)) |
760 | + /* job_class_new() sets path */ |
761 | + if (! state_get_json_string_var (json, "path", NULL, path)) |
762 | + goto error; |
763 | + |
764 | + nih_assert (! strcmp (class->path, path)); |
765 | + |
766 | + nih_free (class->instance); |
767 | + if (! state_get_json_string_var_to_obj (json, class, instance)) |
768 | + goto error; |
769 | + |
770 | + if (! state_get_json_string_var_to_obj (json, class, description)) |
771 | + goto error; |
772 | + |
773 | + if (! state_get_json_string_var_to_obj (json, class, author)) |
774 | + goto error; |
775 | + |
776 | + if (! state_get_json_string_var_to_obj (json, class, version)) |
777 | + goto error; |
778 | + |
779 | + if (! state_get_json_env_array_to_obj (json, class, env)) |
780 | + goto error; |
781 | + |
782 | + if (! state_get_json_env_array_to_obj (json, class, export)) |
783 | goto error; |
784 | |
785 | /* start and stop conditions are optional */ |
786 | @@ -1885,8 +1881,8 @@ |
787 | goto error; |
788 | |
789 | if (*start_on) { |
790 | - partial->start_on = parse_on_simple (partial, "start", start_on); |
791 | - if (! partial->start_on) { |
792 | + class->start_on = parse_on_simple (class, "start", start_on); |
793 | + if (! class->start_on) { |
794 | NihError *err; |
795 | |
796 | err = nih_error_get (); |
797 | @@ -1910,8 +1906,8 @@ |
798 | goto error; |
799 | |
800 | if (*stop_on) { |
801 | - partial->stop_on = parse_on_simple (partial, "stop", stop_on); |
802 | - if (! partial->stop_on) { |
803 | + class->stop_on = parse_on_simple (class, "stop", stop_on); |
804 | + if (! class->stop_on) { |
805 | NihError *err; |
806 | |
807 | err = nih_error_get (); |
808 | @@ -1928,73 +1924,102 @@ |
809 | } |
810 | } |
811 | |
812 | - if (! state_get_json_str_array_to_obj (json, partial, emits)) |
813 | + if (! state_get_json_str_array_to_obj (json, class, emits)) |
814 | goto error; |
815 | |
816 | /* 'process' must be handled by caller */ |
817 | |
818 | if (! state_get_json_enum_var (json, |
819 | job_class_expect_type_str_to_enum, |
820 | - "expect", partial->expect)) |
821 | + "expect", class->expect)) |
822 | goto error; |
823 | |
824 | - if (! state_get_json_int_var_to_obj (json, partial, task)) |
825 | - goto error; |
826 | - |
827 | - if (! state_get_json_int_var_to_obj (json, partial, kill_timeout)) |
828 | - goto error; |
829 | - |
830 | - if (! state_get_json_int_var_to_obj (json, partial, kill_signal)) |
831 | - goto error; |
832 | - |
833 | - if (! state_get_json_int_var_to_obj (json, partial, respawn)) |
834 | - goto error; |
835 | - |
836 | - if (! state_get_json_int_var_to_obj (json, partial, respawn_limit)) |
837 | - goto error; |
838 | - |
839 | - if (! state_get_json_int_var_to_obj (json, partial, respawn_interval)) |
840 | + if (! state_get_json_int_var_to_obj (json, class, task)) |
841 | + goto error; |
842 | + |
843 | + if (! state_get_json_int_var_to_obj (json, class, kill_timeout)) |
844 | + goto error; |
845 | + |
846 | + if (! state_get_json_int_var_to_obj (json, class, kill_signal)) |
847 | + goto error; |
848 | + |
849 | + if (! state_get_json_int_var_to_obj (json, class, respawn)) |
850 | + goto error; |
851 | + |
852 | + if (! state_get_json_int_var_to_obj (json, class, respawn_limit)) |
853 | + goto error; |
854 | + |
855 | + if (! state_get_json_int_var_to_obj (json, class, respawn_interval)) |
856 | goto error; |
857 | |
858 | if (! state_get_json_enum_var (json, |
859 | job_class_console_type_str_to_enum, |
860 | - "console", partial->console)) |
861 | - goto error; |
862 | - |
863 | - if (! state_get_json_int_var_to_obj (json, partial, umask)) |
864 | - goto error; |
865 | - |
866 | - if (! state_get_json_int_var_to_obj (json, partial, nice)) |
867 | - goto error; |
868 | - |
869 | - if (! state_get_json_int_var_to_obj (json, partial, oom_score_adj)) |
870 | - goto error; |
871 | - |
872 | - if (! state_get_json_string_var_to_obj (json, partial, chroot)) |
873 | - goto error; |
874 | - |
875 | - if (! state_get_json_string_var_to_obj (json, partial, chdir)) |
876 | - goto error; |
877 | - |
878 | - if (! state_get_json_string_var_to_obj (json, partial, setuid)) |
879 | - goto error; |
880 | - |
881 | - if (! state_get_json_string_var_to_obj (json, partial, setgid)) |
882 | - goto error; |
883 | - |
884 | - if (! state_get_json_int_var_to_obj (json, partial, deleted)) |
885 | - goto error; |
886 | - |
887 | - if (! state_get_json_int_var_to_obj (json, partial, debug)) |
888 | - goto error; |
889 | - |
890 | - if (! state_get_json_string_var_to_obj (json, partial, usage)) |
891 | - goto error; |
892 | - |
893 | - return partial; |
894 | + "console", class->console)) |
895 | + goto error; |
896 | + |
897 | + if (! state_get_json_int_var_to_obj (json, class, umask)) |
898 | + goto error; |
899 | + |
900 | + if (! state_get_json_int_var_to_obj (json, class, nice)) |
901 | + goto error; |
902 | + |
903 | + if (! state_get_json_int_var_to_obj (json, class, oom_score_adj)) |
904 | + goto error; |
905 | + |
906 | + if (! state_get_json_string_var_to_obj (json, class, chroot)) |
907 | + goto error; |
908 | + |
909 | + if (! state_get_json_string_var_to_obj (json, class, chdir)) |
910 | + goto error; |
911 | + |
912 | + if (! state_get_json_string_var_to_obj (json, class, setuid)) |
913 | + goto error; |
914 | + |
915 | + if (! state_get_json_string_var_to_obj (json, class, setgid)) |
916 | + goto error; |
917 | + |
918 | + if (! state_get_json_int_var_to_obj (json, class, deleted)) |
919 | + goto error; |
920 | + |
921 | + if (! state_get_json_int_var_to_obj (json, class, debug)) |
922 | + goto error; |
923 | + |
924 | + if (! state_get_json_string_var_to_obj (json, class, usage)) |
925 | + goto error; |
926 | + |
927 | + json_normalexit = json_object_object_get (json, "normalexit"); |
928 | + if (! json_normalexit) |
929 | + goto error; |
930 | + |
931 | + ret = state_deserialise_int_array (class, json_normalexit, |
932 | + int, &class->normalexit, &class->normalexit_len); |
933 | + if (ret < 0) |
934 | + goto error; |
935 | + |
936 | + if (state_rlimit_deserialise_all (json, class, &class->limits) < 0) |
937 | + goto error; |
938 | + |
939 | + if (process_deserialise_all (json, class->process, class->process) < 0) |
940 | + goto error; |
941 | + |
942 | + /* Force class to be known. |
943 | + * |
944 | + * We cannot use job_class_*consider() since the |
945 | + * JobClasses have no associated ConfFile. |
946 | + */ |
947 | + job_class_add_safe (class); |
948 | + |
949 | + /* Any jobs must be added after the class is registered |
950 | + * (since you cannot add a job to a partially-created |
951 | + * class). |
952 | + */ |
953 | + if (job_deserialise_all (class, json) < 0) |
954 | + goto error; |
955 | + |
956 | + return class; |
957 | |
958 | error: |
959 | - nih_free (partial); |
960 | + nih_free (class); |
961 | return NULL; |
962 | } |
963 | |
964 | @@ -2010,9 +2035,7 @@ |
965 | int |
966 | job_class_deserialise_all (json_object *json) |
967 | { |
968 | - json_object *json_normalexit; |
969 | JobClass *class = NULL; |
970 | - int ret; |
971 | |
972 | nih_assert (json); |
973 | |
974 | @@ -2028,7 +2051,6 @@ |
975 | |
976 | for (int i = 0; i < json_object_array_length (json_classes); i++) { |
977 | json_object *json_class; |
978 | - nih_local JobClass *partial = NULL; |
979 | |
980 | json_class = json_object_array_get_idx (json_classes, i); |
981 | if (! json_class) |
982 | @@ -2037,12 +2059,10 @@ |
983 | if (! state_check_json_type (json_class, object)) |
984 | goto error; |
985 | |
986 | - partial = job_class_deserialise (json_class); |
987 | - if (! partial) |
988 | + class = job_class_deserialise (json_class); |
989 | + if (! class) |
990 | goto error; |
991 | |
992 | - class = NIH_MUST (job_class_new (NULL, partial->name, partial->session)); |
993 | - |
994 | /* FIXME: |
995 | * |
996 | * If user sessions exist (ie 'initctl --session list' |
997 | @@ -2053,105 +2073,6 @@ |
998 | * |
999 | */ |
1000 | |
1001 | - /* job_class_new() sets path */ |
1002 | - nih_assert (! strcmp (class->path, partial->path)); |
1003 | - |
1004 | - if (! state_partial_copy_string (class, partial, description)) |
1005 | - goto error; |
1006 | - |
1007 | - if (! state_partial_copy_string (class, partial, author)) |
1008 | - goto error; |
1009 | - |
1010 | - if (! state_partial_copy_string (class, partial, version)) |
1011 | - goto error; |
1012 | - |
1013 | - if (! state_partial_copy_string (class, partial, chroot)) |
1014 | - goto error; |
1015 | - |
1016 | - if (! state_partial_copy_string (class, partial, chdir)) |
1017 | - goto error; |
1018 | - |
1019 | - if (! state_partial_copy_string (class, partial, setuid)) |
1020 | - goto error; |
1021 | - |
1022 | - if (! state_partial_copy_string (class, partial, setgid)) |
1023 | - goto error; |
1024 | - |
1025 | - if (! state_partial_copy_string (class, partial, usage)) |
1026 | - goto error; |
1027 | - |
1028 | - state_partial_copy_int (class, partial, expect); |
1029 | - state_partial_copy_int (class, partial, task); |
1030 | - state_partial_copy_int (class, partial, kill_timeout); |
1031 | - state_partial_copy_int (class, partial, kill_signal); |
1032 | - state_partial_copy_int (class, partial, respawn); |
1033 | - state_partial_copy_int (class, partial, respawn_limit); |
1034 | - state_partial_copy_int (class, partial, respawn_interval); |
1035 | - |
1036 | - json_normalexit = json_object_object_get (json_class, "normalexit"); |
1037 | - if (! json_normalexit) |
1038 | - goto error; |
1039 | - |
1040 | - ret = state_deserialise_int_array (class, json_normalexit, |
1041 | - int, &class->normalexit, &class->normalexit_len); |
1042 | - if (ret < 0) |
1043 | - goto error; |
1044 | - |
1045 | - state_partial_copy_int (class, partial, console); |
1046 | - state_partial_copy_int (class, partial, umask); |
1047 | - state_partial_copy_int (class, partial, nice); |
1048 | - state_partial_copy_int (class, partial, oom_score_adj); |
1049 | - state_partial_copy_int (class, partial, deleted); |
1050 | - state_partial_copy_int (class, partial, debug); |
1051 | - |
1052 | - if (state_rlimit_deserialise_all (json_class, class, &class->limits) < 0) |
1053 | - goto error; |
1054 | - |
1055 | - if (! state_copy_str_array_to_obj (class, partial, env)) |
1056 | - goto error; |
1057 | - |
1058 | - if (! state_copy_str_array_to_obj (class, partial, export)) |
1059 | - goto error; |
1060 | - |
1061 | - if (! state_copy_str_array_to_obj (class, partial, emits)) |
1062 | - goto error; |
1063 | - |
1064 | - if (! state_copy_event_oper_to_obj (class, partial, start_on)) |
1065 | - goto error; |
1066 | - |
1067 | - if (! state_copy_event_oper_to_obj (class, partial, stop_on)) |
1068 | - goto error; |
1069 | - |
1070 | - if (process_deserialise_all (json_class, class->process, class->process) < 0) |
1071 | - goto error; |
1072 | - |
1073 | - /* instance must have a value, but only set it if the |
1074 | - * partial value differs from the default set by |
1075 | - * job_class_new(). |
1076 | - */ |
1077 | - if (partial->instance && *partial->instance) { |
1078 | - nih_free (class->instance); |
1079 | - |
1080 | - class->instance = NIH_MUST (nih_strdup (class, partial->instance)); |
1081 | - } |
1082 | - |
1083 | - /* Force class to be known. |
1084 | - * |
1085 | - * We cannot use job_class_*consider() since the |
1086 | - * JobClasses have no associated ConfFile. |
1087 | - */ |
1088 | - job_class_add_safe (class); |
1089 | - |
1090 | - /* Any jobs must be added after the class is registered |
1091 | - * (since you cannot add a job to a partially-created |
1092 | - * class). |
1093 | - * |
1094 | - * Associated jobs are handled here rather than in |
1095 | - * job_class_deserialise() to avoid yet more data copying |
1096 | - * from 'partial' to 'class'. |
1097 | - */ |
1098 | - if (job_deserialise_all (class, json_class) < 0) |
1099 | - goto error; |
1100 | } |
1101 | |
1102 | return 0; |
1103 | |
1104 | === modified file 'init/log.c' |
1105 | --- init/log.c 2012-09-10 16:00:32 +0000 |
1106 | +++ init/log.c 2012-09-11 00:41:20 +0000 |
1107 | @@ -896,22 +896,23 @@ |
1108 | * log_deserialise: |
1109 | * @json: JSON-serialised Log object to deserialise. |
1110 | * |
1111 | - * Convert @json into a partial Log object. |
1112 | - * |
1113 | - * Note that the object returned is not a true Log since not all |
1114 | - * structure elements are encoded in the JSON. |
1115 | - * |
1116 | - * Returns: partial Log object, or NULL on error. |
1117 | + * Convert @json into a Log object. |
1118 | + * |
1119 | + * Returns: Log object, or NULL on error. |
1120 | **/ |
1121 | Log * |
1122 | -log_deserialise (json_object *json) |
1123 | +log_deserialise (const void *parent, |
1124 | + json_object *json) |
1125 | { |
1126 | - Log *partial; |
1127 | + Log *log; |
1128 | nih_local char *unflushed_hex = NULL; |
1129 | nih_local char *unflushed = NULL; |
1130 | int ret; |
1131 | size_t len; |
1132 | json_object *json_unflushed; |
1133 | + nih_local char *path = NULL; |
1134 | + int fd; |
1135 | + uid_t uid; |
1136 | |
1137 | nih_assert (json); |
1138 | |
1139 | @@ -920,34 +921,39 @@ |
1140 | if (! state_check_json_type (json, object)) |
1141 | return NULL; |
1142 | |
1143 | - partial = nih_new (NULL, Log); |
1144 | - if (! partial) |
1145 | + if (! state_get_json_string_var (json, "path", NULL, path)) |
1146 | return NULL; |
1147 | |
1148 | - memset (partial, '\0', sizeof (Log)); |
1149 | - |
1150 | - if (! state_get_json_string_var_to_obj (json, partial, path)) |
1151 | - goto error; |
1152 | - |
1153 | - if (! *partial->path) { |
1154 | + if (! *path) { |
1155 | /* placeholder log object */ |
1156 | - return partial; |
1157 | + return NULL; |
1158 | } |
1159 | |
1160 | - if (! state_get_json_int_var_to_obj (json, partial, fd)) |
1161 | + if (! state_get_json_int_var (json, "io_watch_fd", fd)) |
1162 | + return NULL; |
1163 | + |
1164 | + /* re-apply CLOEXEC flag to stop fd being leaked to children */ |
1165 | + if (fd != -1 && state_toggle_cloexec (fd, TRUE) < 0) |
1166 | + return NULL; |
1167 | + |
1168 | + if (! state_get_json_int_var (json, "uid", uid)) |
1169 | + return NULL; |
1170 | + |
1171 | + log = log_new (parent, path, fd, uid); |
1172 | + if (! log) |
1173 | + return NULL; |
1174 | + |
1175 | + if (! state_get_json_int_var_to_obj (json, log, fd)) |
1176 | goto error; |
1177 | |
1178 | /* Stop fd leaking to children */ |
1179 | - if (partial->fd != -1) { |
1180 | - if (state_toggle_cloexec (partial->fd, TRUE) < 0) |
1181 | + if (log->fd != -1) { |
1182 | + if (state_toggle_cloexec (log->fd, TRUE) < 0) |
1183 | goto error; |
1184 | } |
1185 | |
1186 | - if (! state_get_json_int_var_to_obj (json, partial, uid)) |
1187 | - goto error; |
1188 | - |
1189 | - partial->unflushed = nih_io_buffer_new (partial); |
1190 | - if (! partial->unflushed) |
1191 | + log->unflushed = nih_io_buffer_new (log); |
1192 | + if (! log->unflushed) |
1193 | goto error; |
1194 | |
1195 | json_unflushed = json_object_object_get (json, "unflushed"); |
1196 | @@ -964,22 +970,22 @@ |
1197 | if (ret < 0) |
1198 | goto error; |
1199 | |
1200 | - if (nih_io_buffer_push (partial->unflushed, unflushed, len) < 0) |
1201 | + if (nih_io_buffer_push (log->unflushed, unflushed, len) < 0) |
1202 | goto error; |
1203 | } |
1204 | |
1205 | - if (! state_get_json_int_var_to_obj (json, partial, detached)) |
1206 | - goto error; |
1207 | - |
1208 | - if (! state_get_json_int_var_to_obj (json, partial, remote_closed)) |
1209 | - goto error; |
1210 | - |
1211 | - if (! state_get_json_int_var_to_obj (json, partial, open_errno)) |
1212 | - goto error; |
1213 | - |
1214 | - return partial; |
1215 | + if (! state_get_json_int_var_to_obj (json, log, detached)) |
1216 | + goto error; |
1217 | + |
1218 | + if (! state_get_json_int_var_to_obj (json, log, remote_closed)) |
1219 | + goto error; |
1220 | + |
1221 | + if (! state_get_json_int_var_to_obj (json, log, open_errno)) |
1222 | + goto error; |
1223 | + |
1224 | + return log; |
1225 | |
1226 | error: |
1227 | - nih_free (partial); |
1228 | + nih_free (log); |
1229 | return NULL; |
1230 | } |
1231 | |
1232 | === modified file 'init/log.h' |
1233 | --- init/log.h 2012-09-03 16:00:18 +0000 |
1234 | +++ init/log.h 2012-09-11 00:41:20 +0000 |
1235 | @@ -90,7 +90,7 @@ |
1236 | void log_unflushed_init (void); |
1237 | json_object * log_serialise (Log *log) |
1238 | __attribute__ ((warn_unused_result, malloc)); |
1239 | -Log * log_deserialise (json_object *json) |
1240 | +Log * log_deserialise (const void *parent, json_object *json) |
1241 | __attribute__ ((warn_unused_result, malloc)); |
1242 | |
1243 | NIH_END_EXTERN |
1244 | |
1245 | === modified file 'init/process.c' |
1246 | --- init/process.c 2012-08-28 16:29:50 +0000 |
1247 | +++ init/process.c 2012-09-11 00:41:20 +0000 |
1248 | @@ -209,17 +209,9 @@ |
1249 | * |
1250 | * Convert @json into a Process object. |
1251 | * |
1252 | - * Caller must manually nih_ref() returned object to a parent object. |
1253 | - * |
1254 | * Returns: Process object, or NULL on error. |
1255 | **/ |
1256 | |
1257 | -#if 1 |
1258 | -/* FIXME: should we just make this the same as the other partial |
1259 | - * objects for consistency? |
1260 | - */ |
1261 | -#endif |
1262 | - |
1263 | static Process * |
1264 | process_deserialise (json_object *json, const void *parent) |
1265 | { |
1266 | @@ -232,14 +224,22 @@ |
1267 | |
1268 | process = NIH_MUST (process_new (parent)); |
1269 | |
1270 | - memset (process, '\0', sizeof (Process)); |
1271 | - |
1272 | if (! state_get_json_int_var_to_obj (json, process, script)) |
1273 | goto error; |
1274 | |
1275 | if (! state_get_json_string_var_to_obj (json, process, command)) |
1276 | goto error; |
1277 | |
1278 | + /* All Process slots have to be serialised in the JSON to |
1279 | + * guarantee ordering on deserialisation. |
1280 | + * |
1281 | + * However, here we've found a Process that was merely |
1282 | + * an ordering placeholder - no command has been defined, |
1283 | + * so ignore it. |
1284 | + */ |
1285 | + if (! process->command || ! *process->command) |
1286 | + goto error; |
1287 | + |
1288 | return process; |
1289 | |
1290 | error: |
1291 | @@ -265,7 +265,6 @@ |
1292 | { |
1293 | json_object *json_processes; |
1294 | Process *process; |
1295 | - nih_local Process *partial = NULL; |
1296 | int i; |
1297 | |
1298 | nih_assert (json); |
1299 | @@ -292,27 +291,8 @@ |
1300 | if (! state_check_json_type (json_process, object)) |
1301 | goto error; |
1302 | |
1303 | - partial = process_deserialise (json_process, partial); |
1304 | - if (! partial) |
1305 | - goto error; |
1306 | - |
1307 | - /* All Process slots have to be serialised in the JSON to |
1308 | - * guarantee ordering on deserialisation. |
1309 | - * |
1310 | - * However, here we've found a Process that was merely |
1311 | - * an ordering placeholder - no command has been defined, |
1312 | - * so ignore it. |
1313 | - */ |
1314 | - if (! partial->command || ! *partial->command) { |
1315 | - processes[i] = NULL; |
1316 | - continue; |
1317 | - } |
1318 | - |
1319 | - process = NIH_MUST (process_new (parent)); |
1320 | - process->command = NIH_MUST (nih_strdup (processes, partial->command)); |
1321 | - process->script = partial->script; |
1322 | - |
1323 | - processes[i] = process; |
1324 | + processes[i] = process_deserialise (json_process, parent); |
1325 | + |
1326 | } |
1327 | |
1328 | return 0; |
1329 | |
1330 | === modified file 'init/session.c' |
1331 | --- init/session.c 2012-09-04 21:51:27 +0000 |
1332 | +++ init/session.c 2012-09-11 00:41:20 +0000 |
1333 | @@ -476,42 +476,47 @@ |
1334 | * session_deserialise: |
1335 | * @json: JSON-serialised Session object to deserialise. |
1336 | * |
1337 | - * Convert @json into a partial Session object. |
1338 | - * |
1339 | - * Note that the object returned is not a true Session since not all |
1340 | - * structure elements are encoded in the JSON. |
1341 | - * |
1342 | - * Returns: partial Session object, or NULL on error. |
1343 | + * Convert @json into a Session object. |
1344 | + * |
1345 | + * Returns: Session object, or NULL on error. |
1346 | **/ |
1347 | static Session * |
1348 | session_deserialise (json_object *json) |
1349 | { |
1350 | - Session *partial; |
1351 | + Session *session; |
1352 | + nih_local const char *chroot; |
1353 | + uid_t user; |
1354 | |
1355 | nih_assert (json); |
1356 | |
1357 | if (! state_check_json_type (json, object)) |
1358 | return NULL; |
1359 | |
1360 | - partial = nih_new (NULL, Session); |
1361 | - if (! partial) |
1362 | - return NULL; |
1363 | - |
1364 | - memset (partial, '\0', sizeof (Session)); |
1365 | - |
1366 | - if (! state_get_json_string_var_to_obj (json, partial, chroot)) |
1367 | - goto error; |
1368 | - |
1369 | - if (! state_get_json_int_var_to_obj (json, partial, user)) |
1370 | - goto error; |
1371 | - |
1372 | - if (! state_get_json_string_var_to_obj (json, partial, conf_path)) |
1373 | - goto error; |
1374 | - |
1375 | - return partial; |
1376 | + if (! state_get_json_string_var (json, "chroot", NULL, chroot)) |
1377 | + return NULL; |
1378 | + |
1379 | + if (! state_get_json_int_var (json, "user", user)) |
1380 | + return NULL; |
1381 | + |
1382 | + /* Create a new session */ |
1383 | + session = NIH_MUST (session_new (NULL, chroot, user)); |
1384 | + |
1385 | + if (! state_get_json_string_var_to_obj (json, session, conf_path)) |
1386 | + goto error; |
1387 | + |
1388 | + /* Not an error, just the representation of the "NULL session" */ |
1389 | + if (! *session->chroot && ! session->user && ! *session->conf_path) |
1390 | + goto error; |
1391 | + |
1392 | + if (! *session->chroot) |
1393 | + { |
1394 | + nih_free (session->chroot); |
1395 | + session->chroot = NULL; |
1396 | + } |
1397 | + return session; |
1398 | |
1399 | error: |
1400 | - nih_free (partial); |
1401 | + nih_free (session); |
1402 | return NULL; |
1403 | } |
1404 | |
1405 | @@ -528,7 +533,6 @@ |
1406 | session_deserialise_all (json_object *json) |
1407 | { |
1408 | Session *session; |
1409 | - nih_local Session *partial = NULL; |
1410 | |
1411 | nih_assert (json); |
1412 | |
1413 | @@ -554,22 +558,14 @@ |
1414 | if (! state_check_json_type (json_session, object)) |
1415 | goto error; |
1416 | |
1417 | - partial = session_deserialise (json_session); |
1418 | - if (! partial) |
1419 | - goto error; |
1420 | - |
1421 | - if (! *partial->chroot && ! partial->user && ! *partial->conf_path) { |
1422 | - /* Ignore the "NULL session" which is represented |
1423 | - * by NULL, not an "empty session" internally. |
1424 | - */ |
1425 | + session = session_deserialise (json_session); |
1426 | + /* Ignore the "NULL session" which is represented |
1427 | + * by NULL, not an "empty session" internally. |
1428 | + */ |
1429 | + if (! session) |
1430 | continue; |
1431 | - } |
1432 | |
1433 | - /* Create a new session and associated ConfSource */ |
1434 | - session = NIH_MUST (session_new (NULL, |
1435 | - *partial->chroot ? partial->chroot : NULL, |
1436 | - partial->user)); |
1437 | - session->conf_path = NIH_MUST (nih_strdup (session, partial->conf_path)); |
1438 | + /* Create the associated ConfSource */ |
1439 | session_create_conf_source (session, TRUE); |
1440 | } |
1441 | |
1442 | |
1443 | === modified file 'init/state.h' |
1444 | --- init/state.h 2012-09-10 10:30:28 +0000 |
1445 | +++ init/state.h 2012-09-11 00:41:20 +0000 |
1446 | @@ -106,23 +106,6 @@ |
1447 | * into an array of Process objects which are then hooked onto a |
1448 | * JobClass object). |
1449 | * |
1450 | - * Note that objects returned by <object_>_deserialise() are generally |
1451 | - * _partial_ objects: they are not true objects since they have not |
1452 | - * been constructed. They are like templates for the real objects with |
1453 | - * those elements filled in that the JSON encodes. |
1454 | - * |
1455 | - * Each partial object needs to be converted into a real object by: |
1456 | - * |
1457 | - * - creating an instance of that object (using <object_>_new()). |
1458 | - * - copying the element data from the partial object back into the real |
1459 | - * object. |
1460 | - * |
1461 | - * These steps happens in <object_>_deserialise_all(). It is rather |
1462 | - * tedious but does ensure that the resultant object is "sane". It |
1463 | - * is also essential since the JSON representation of most objects does |
1464 | - * _NOT_ encode all information about an object (for example the JSON |
1465 | - * encoding for an Event does not encode 'blockers' and 'blocking'). |
1466 | - * |
1467 | * == Error Handling == |
1468 | * |
1469 | * If stateful re-exec fails, Upstart must perform a stateless reexec: |