Merge lp:~vorlon/upstart/stateful-reexec-confsource into lp:~jamesodhunt/upstart/stateful-reexec
- stateful-reexec-confsource
- Merge into stateful-reexec
Status: | Merged |
---|---|
Merged at revision: | 1438 |
Proposed branch: | lp:~vorlon/upstart/stateful-reexec-confsource |
Merge into: | lp:~jamesodhunt/upstart/stateful-reexec |
Diff against target: |
3037 lines (+650/-1298) 25 files modified
ChangeLog (+4/-0) dbus/com.ubuntu.Upstart.xml (+0/-8) init/Makefile.am (+1/-1) init/conf.c (+10/-51) init/conf.h (+3/-3) init/control.c (+28/-482) init/control.h (+1/-22) init/errors.h (+0/-2) init/event.c (+32/-47) init/event_operator.c (+1/-1) init/job.c (+159/-218) init/job_class.c (+210/-240) init/job_class.h (+2/-0) init/log.c (+121/-60) init/log.h (+2/-2) init/main.c (+7/-4) init/parse_job.c (+1/-1) init/paths.h (+0/-28) init/process.c (+12/-32) init/session.c (+35/-43) init/state.c (+3/-25) init/state.h (+9/-19) init/tests/test_conf.c (+1/-1) init/tests/test_control.c (+7/-7) init/tests/test_event_operator.c (+1/-1) |
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+121541@code.launchpad.net |
Commit message
Description of the change
Simplify the serialization/
With these changes, I've done a successful stateful reexec for the first time in my test VM - though note that if I try to do so with a full complement of jobs, it fails for me with:
init:BUG: parse error: Mismatched parentheses
This message seems to come from either the job or job class start/stop rule deserialization. I haven't yet figured out which job is to blame. Looking at the dumped json file, I think it may be from /etc/init/tty4.conf (et al) and mis-serialization of rules with newlines in them.
- 1435. By Steve Langasek
-
Merge latest changes from James' branch
- 1436. By Steve Langasek
-
Resync with James' branch.
- 1437. By Steve Langasek
-
Resync with James' branch.
- 1438. By Steve Langasek
-
Resync with the main branch
- 1439. By Steve Langasek
-
clean up 'partial' handling for Event deserialization
- 1440. By Steve Langasek
-
Resync with the main branch
- 1441. By Steve Langasek
-
clean up 'partial' handling of Log deserialization
- 1442. By Steve Langasek
-
Resync with the main branch
- 1443. By Steve Langasek
-
clean up 'partial' handling of Process deserialization
- 1444. By Steve Langasek
-
clean up 'partial' handling of Session deserialization
- 1445. By Steve Langasek
-
Finally, drop the comments in state.h about the right way to deserialize
involving returning partial objects; there's just no need for allocating
twice and copying contents around when we can just make sure we always
deserialize the bits needed for the object constructor first, then populate
everything in one go. - 1446. By Steve Langasek
-
Resync with the main branch
- 1447. By Steve Langasek
-
Resync with the main branch
- 1448. By Steve Langasek
-
adjust comments to reflect the code that's changed
Preview Diff
1 | === modified file 'ChangeLog' |
2 | --- ChangeLog 2012-05-23 13:27:13 +0000 |
3 | +++ ChangeLog 2012-09-11 00:41:22 +0000 |
4 | @@ -1,3 +1,7 @@ |
5 | +2012-09-10 James Hunt <james.hunt@ubuntu.com> |
6 | + |
7 | + * Merged lp:~jconti/upstart/fix_empty_chroot. |
8 | + |
9 | 2012-05-23 James Hunt <james.hunt@ubuntu.com> |
10 | |
11 | * init/main.c: Add in "bare" re-exec handling from Ubuntu |
12 | |
13 | === modified file 'dbus/com.ubuntu.Upstart.xml' |
14 | --- dbus/com.ubuntu.Upstart.xml 2012-08-10 14:06:25 +0000 |
15 | +++ dbus/com.ubuntu.Upstart.xml 2012-09-11 00:41:22 +0000 |
16 | @@ -42,14 +42,6 @@ |
17 | <arg name="job" type="o" /> |
18 | </signal> |
19 | |
20 | - <method name="DebugSerialise"> |
21 | - <arg name="json" type="s" direction="out" /> |
22 | - </method> |
23 | - |
24 | - <method name="DebugDeserialise"> |
25 | - <arg name="json" type="s" direction="in" /> |
26 | - </method> |
27 | - |
28 | <!-- Event emission --> |
29 | <method name="EmitEvent"> |
30 | <annotation name="com.netsplit.Nih.Method.Async" value="true" /> |
31 | |
32 | === modified file 'init/Makefile.am' |
33 | --- init/Makefile.am 2012-08-24 16:42:22 +0000 |
34 | +++ init/Makefile.am 2012-09-11 00:41:22 +0000 |
35 | @@ -42,7 +42,7 @@ |
36 | environ.c environ.h \ |
37 | process.c process.h \ |
38 | session.c session.h \ |
39 | - state.c state.h \ |
40 | + state.c state.h \ |
41 | job_class.c job_class.h \ |
42 | job_process.c job_process.h \ |
43 | job.c job.h \ |
44 | |
45 | === modified file 'init/conf.c' |
46 | --- init/conf.c 2012-08-24 16:28:07 +0000 |
47 | +++ init/conf.c 2012-09-11 00:41:22 +0000 |
48 | @@ -94,13 +94,6 @@ |
49 | |
50 | |
51 | /** |
52 | - * deserialised: |
53 | - * |
54 | - * TRUE if configuration is being parsed after deserialisation. |
55 | - **/ |
56 | -static int deserialised = FALSE; |
57 | - |
58 | -/** |
59 | * is_conf_file_std: |
60 | * @path: path to check. |
61 | * |
62 | @@ -336,9 +329,6 @@ |
63 | /** |
64 | * conf_reload: |
65 | * |
66 | - * @_deserialised: TRUE if called _immediately_ after deserialisation, |
67 | - * else FALSE. |
68 | - * |
69 | * Reloads all configuration sources. |
70 | * |
71 | * Watches on new configuration sources are established so that future |
72 | @@ -350,16 +340,10 @@ |
73 | * parse no configuration without error. |
74 | **/ |
75 | void |
76 | -conf_reload (int _deserialised) |
77 | +conf_reload (void) |
78 | { |
79 | conf_init (); |
80 | |
81 | - /* Indicate that existing JobClasses are to be used, rather than |
82 | - * reparsing configuration files. |
83 | - */ |
84 | - if (_deserialised) |
85 | - deserialised = TRUE; |
86 | - |
87 | NIH_LIST_FOREACH (conf_sources, iter) { |
88 | ConfSource *source = (ConfSource *)iter; |
89 | |
90 | @@ -374,14 +358,6 @@ |
91 | nih_free (err); |
92 | } |
93 | } |
94 | - |
95 | - /* Now the ConfFiles are associated with the deserialised |
96 | - * JobClasses, we can forget about deserialisation such that all |
97 | - * future file changes will recreate the JobClasses if |
98 | - * necessary. |
99 | - */ |
100 | - if (_deserialised) |
101 | - deserialised = FALSE; |
102 | } |
103 | |
104 | /** |
105 | @@ -958,7 +934,7 @@ |
106 | * @path: path of conf file to be reloaded. |
107 | * @override_path: if not NULL and @path refers to a path associated with @source, |
108 | * overlay the contents of @path into the existing @source entry for |
109 | - * @path. If FALSE, discard any existing knowledge of @path, |
110 | + * @path. If FALSE, discard any existing knowledge of @path. |
111 | * |
112 | * This function is used to parse the file at @path (or @override_path) in the |
113 | * context of the given configuration @source. Necessary ConfFile structures |
114 | @@ -986,7 +962,6 @@ |
115 | size_t len, pos, lineno; |
116 | NihError *err = NULL; |
117 | const char *path_to_load; |
118 | - JobClass *existing; |
119 | |
120 | nih_assert (source != NULL); |
121 | nih_assert (path != NULL); |
122 | @@ -1067,29 +1042,13 @@ |
123 | nih_debug ("Loading %s from %s", name, path); |
124 | } |
125 | |
126 | - if (deserialised) { |
127 | - job_class_init (); |
128 | - |
129 | - existing = job_class_get (name, source->session); |
130 | - |
131 | - /* Found an existing job class created via the |
132 | - * deserialisation process, so use that rather |
133 | - * than reparsing the file. |
134 | - */ |
135 | - if (existing) { |
136 | - file->job = existing; |
137 | - nih_debug ("Using existing deserialised JobClass for %s", name); |
138 | - } |
139 | - |
140 | + file->job = parse_job (NULL, source->session, file->job, |
141 | + name, buf, len, &pos, &lineno); |
142 | + |
143 | + if (file->job) { |
144 | + job_class_consider (file->job); |
145 | } else { |
146 | - file->job = parse_job (NULL, source->session, file->job, |
147 | - name, buf, len, &pos, &lineno); |
148 | - |
149 | - if (file->job) { |
150 | - job_class_consider (file->job); |
151 | - } else { |
152 | - err = nih_error_get (); |
153 | - } |
154 | + err = nih_error_get (); |
155 | } |
156 | |
157 | break; |
158 | @@ -1227,7 +1186,7 @@ |
159 | return NULL; |
160 | } |
161 | |
162 | -//#ifdef DEBUG |
163 | +#ifdef DEBUG |
164 | |
165 | size_t |
166 | debug_count_list_entries (const NihList *list) |
167 | @@ -1428,5 +1387,5 @@ |
168 | } |
169 | } |
170 | |
171 | -//#endif /* DEBUG */ |
172 | +#endif /* DEBUG */ |
173 | |
174 | |
175 | === modified file 'init/conf.h' |
176 | --- init/conf.h 2012-08-23 17:01:48 +0000 |
177 | +++ init/conf.h 2012-09-11 00:41:22 +0000 |
178 | @@ -119,7 +119,7 @@ |
179 | ConfFile * conf_file_new (ConfSource *source, const char *path) |
180 | __attribute__ ((warn_unused_result, malloc)); |
181 | |
182 | -void conf_reload (int _deserialised); |
183 | +void conf_reload (void); |
184 | int conf_source_reload (ConfSource *source) |
185 | __attribute__ ((warn_unused_result)); |
186 | |
187 | @@ -130,7 +130,7 @@ |
188 | char *toggle_conf_name (const void *parent, const char *path) |
189 | __attribute__ ((warn_unused_result, malloc)); |
190 | |
191 | -//#ifdef DEBUG |
192 | +#ifdef DEBUG |
193 | |
194 | /* used for debugging only */ |
195 | #include "job.h" |
196 | @@ -173,7 +173,7 @@ |
197 | debug_show_conf_sources(void) |
198 | __attribute__ ((unused)); |
199 | |
200 | -//#endif |
201 | +#endif |
202 | |
203 | NIH_END_EXTERN |
204 | |
205 | |
206 | === modified file 'init/control.c' |
207 | --- init/control.c 2012-08-24 16:24:40 +0000 |
208 | +++ init/control.c 2012-09-11 00:41:22 +0000 |
209 | @@ -63,26 +63,7 @@ |
210 | static void control_disconnected (DBusConnection *conn); |
211 | static void control_register_all (DBusConnection *conn); |
212 | |
213 | -/* FIXME: temporary function attribute */ |
214 | -#if 1 |
215 | -static void control_clear_cloexec (void) |
216 | - __attribute__ ((unused)); |
217 | -#endif |
218 | - |
219 | static void control_bus_flush (void); |
220 | -static int control_get_connection_fd (DBusConnection *connection) |
221 | - __attribute__ ((warn_unused_result)); |
222 | -static json_object * control_serialise (DBusConnection *connection) |
223 | - __attribute__ ((malloc, warn_unused_result)); |
224 | -static DBusConnection *control_deserialise (json_object *json) |
225 | -#if 0 |
226 | - __attribute__ ((malloc, warn_unused_result)); |
227 | -#else |
228 | -/* FIXME: temporary function attribute */ |
229 | - __attribute__ ((unused)); |
230 | -#endif |
231 | - |
232 | -extern json_object *json_control_conns;; |
233 | |
234 | /** |
235 | * use_session_bus: |
236 | @@ -222,8 +203,6 @@ |
237 | /** |
238 | * control_bus_open: |
239 | * |
240 | - * @restart: specify TRUE on restart, else FALSE. |
241 | - * |
242 | * Open a connection to the appropriate D-Bus bus and store it in the |
243 | * control_bus global. The connection is handled automatically |
244 | * in the main loop. |
245 | @@ -231,45 +210,26 @@ |
246 | * Returns: zero on success, negative value on raised error. |
247 | **/ |
248 | int |
249 | -control_bus_open (int restart) |
250 | +control_bus_open (void) |
251 | { |
252 | DBusConnection *conn; |
253 | DBusError error; |
254 | NihListEntry *entry; |
255 | int ret; |
256 | |
257 | -#if 0 |
258 | - if (restart) { |
259 | - conn = control_bus; |
260 | - if (! conn) { |
261 | - nih_error_raise (CONTROL_REEXEC_ERROR, |
262 | - _(CONTROL_REEXEC_ERROR_STR)); |
263 | - return -1; |
264 | - } |
265 | - dbus_connection_set_exit_on_disconnect (conn, FALSE); |
266 | - |
267 | - if (nih_dbus_setup (conn, control_disconnected) < 0) { |
268 | - dbus_connection_unref (conn); |
269 | - nih_return_no_memory_error (-1); |
270 | - } |
271 | - } else { |
272 | -#endif |
273 | - nih_assert (control_bus == NULL); |
274 | - |
275 | - control_init (); |
276 | - |
277 | - control_handle_bus_type (); |
278 | - |
279 | - /* Connect to the D-Bus System Bus and hook everything up into |
280 | - * our own main loop automatically. |
281 | - */ |
282 | - conn = nih_dbus_bus (use_session_bus ? DBUS_BUS_SESSION : DBUS_BUS_SYSTEM, |
283 | - control_disconnected); |
284 | - if (! conn) |
285 | - return -1; |
286 | -#if 0 |
287 | - } |
288 | -#endif |
289 | + nih_assert (control_bus == NULL); |
290 | + |
291 | + control_init (); |
292 | + |
293 | + control_handle_bus_type (); |
294 | + |
295 | + /* Connect to the D-Bus System Bus and hook everything up into |
296 | + * our own main loop automatically. |
297 | + */ |
298 | + conn = nih_dbus_bus (use_session_bus ? DBUS_BUS_SESSION : DBUS_BUS_SYSTEM, |
299 | + control_disconnected); |
300 | + if (! conn) |
301 | + return -1; |
302 | |
303 | /* Register objects on the bus. */ |
304 | control_register_all (conn); |
305 | @@ -298,20 +258,15 @@ |
306 | } |
307 | |
308 | |
309 | -#if 0 |
310 | - if (! restart) { |
311 | -#endif |
312 | - /* Add the connection to the list */ |
313 | - entry = NIH_MUST (nih_list_entry_new (NULL)); |
314 | - |
315 | - entry->data = conn; |
316 | - |
317 | - nih_list_add (control_conns, &entry->entry); |
318 | - |
319 | - control_bus = conn; |
320 | -#if 0 |
321 | - } |
322 | -#endif |
323 | + /* Add the connection to the list */ |
324 | + entry = NIH_MUST (nih_list_entry_new (NULL)); |
325 | + |
326 | + entry->data = conn; |
327 | + |
328 | + nih_list_add (control_conns, &entry->entry); |
329 | + |
330 | + |
331 | + control_bus = conn; |
332 | |
333 | return 0; |
334 | } |
335 | @@ -355,15 +310,6 @@ |
336 | |
337 | nih_warn (_("Disconnected from system bus")); |
338 | |
339 | -#if 0 |
340 | - if (dbus_bus_release_name (conn, DBUS_SERVICE_UPSTART, &error) < 0) { |
341 | - nih_error ("Unable to release D-Bus name '%s'", DBUS_SERVICE_UPSTART); |
342 | - dbus_error_free (&error); |
343 | - return; |
344 | - } |
345 | - control_bus_flush (); |
346 | -#endif |
347 | - |
348 | control_bus = NULL; |
349 | } |
350 | |
351 | @@ -431,7 +377,7 @@ |
352 | nih_info (_("Reloading configuration")); |
353 | |
354 | /* This can only be called after deserialisation */ |
355 | - conf_reload (FALSE); |
356 | + conf_reload (); |
357 | |
358 | return 0; |
359 | } |
360 | @@ -871,60 +817,6 @@ |
361 | } |
362 | |
363 | /** |
364 | - * control_get_connection_fd: |
365 | - * |
366 | - * @connection: DBusConnection. |
367 | - * |
368 | - * Obtain the file descriptor associated with the specified connection. |
369 | - * |
370 | - * Returns: file descriptor, or -1 on error. |
371 | - **/ |
372 | -int |
373 | -control_get_connection_fd (DBusConnection *connection) |
374 | -{ |
375 | - int fd; |
376 | - |
377 | - nih_assert (connection); |
378 | - |
379 | - if (! dbus_connection_get_unix_fd (connection, &fd)) |
380 | - return -1; |
381 | - |
382 | - return fd; |
383 | -} |
384 | - |
385 | -/** |
386 | - * control_clear_cloexec: |
387 | - * |
388 | - * Clear the close-on-exec flag for the D-Bus control bus. |
389 | - * |
390 | - * Required to ensure D-Bus connections are maintained across a re-exec |
391 | - * since the default is for D-Bus to mark all fds close-on-exec. |
392 | - **/ |
393 | -static void |
394 | -control_clear_cloexec (void) |
395 | -{ |
396 | - control_init (); |
397 | - |
398 | - nih_assert (control_bus); |
399 | - |
400 | - NIH_LIST_FOREACH (control_conns, iter) { |
401 | - NihListEntry *entry = (NihListEntry *)iter; |
402 | - DBusConnection *conn = entry->data; |
403 | - int fd; |
404 | - |
405 | - fd = control_get_connection_fd (conn); |
406 | - |
407 | - if (state_toggle_cloexec (fd, FALSE) < 0) |
408 | - nih_warn (_("Failed to clear control connection CLOEXEC flag")); |
409 | -#if 1 |
410 | - /* FIXME */ |
411 | - nih_message ("XXX: found D-Bus connection %p (fd=%d, control bus=%s)", |
412 | - conn, fd, conn == control_bus ? "yes" : "no"); |
413 | -#endif |
414 | - } |
415 | -} |
416 | - |
417 | -/** |
418 | * control_bus_flush: |
419 | * |
420 | * Drain any remaining messages in the D-Bus queue. |
421 | @@ -960,281 +852,8 @@ |
422 | |
423 | control_bus_flush (); |
424 | |
425 | -#if 1 |
426 | - /* FIXME */ |
427 | - nih_warn ("XXX: WARNING (%s:%d): NOT clearing close-on-exec bit for D-Bus connections yet", |
428 | - __func__, __LINE__); |
429 | -#else |
430 | - control_clear_cloexec (); |
431 | -#endif |
432 | -} |
433 | - |
434 | - |
435 | -/** |
436 | - * control_serialise: |
437 | - * |
438 | - * @connection: DBusConnection. |
439 | - * |
440 | - * Convert DBusConnection to JSON representation. |
441 | - * |
442 | - * Returns: JSON object encoding @connection, or NULL on error. |
443 | - */ |
444 | -static json_object * |
445 | -control_serialise (DBusConnection *connection) |
446 | -{ |
447 | - json_object *json; |
448 | - int fd; |
449 | - //const char *address; |
450 | - |
451 | - nih_assert (connection); |
452 | - nih_assert (control_bus); |
453 | - |
454 | - control_init (); |
455 | - |
456 | - control_handle_bus_type (); |
457 | - |
458 | - json = json_object_new_object (); |
459 | - if (! json) |
460 | - return NULL; |
461 | - |
462 | - fd = control_get_connection_fd (connection); |
463 | - if (fd < 0) |
464 | - goto error; |
465 | - |
466 | - if (! state_set_json_int_var (json, "fd", fd)) |
467 | - goto error; |
468 | - |
469 | - /* FIXME */ |
470 | -#if 0 |
471 | - address = dbus_connection_get_address (connection); |
472 | - if (! address) |
473 | - goto error; |
474 | - |
475 | - if (! state_set_json_string_var (json, "address", address)) |
476 | - goto error; |
477 | -#else |
478 | - nih_warn ("XXX: WARNING (%s:%d): NOT serialising D-Bus connection address yet", |
479 | - __func__, __LINE__); |
480 | -#endif |
481 | - |
482 | - if (connection == control_bus) |
483 | - if (! state_set_json_int_var (json, "control_bus", 1)) |
484 | - goto error; |
485 | - |
486 | - return json; |
487 | - |
488 | -error: |
489 | - json_object_put (json); |
490 | - return NULL; |
491 | - |
492 | -} |
493 | - |
494 | - |
495 | -/** |
496 | - * control_serialise_all: |
497 | - * |
498 | - * Convert existing control connections to JSON representation. |
499 | - * |
500 | - * This is achieved minimally by: |
501 | - * |
502 | - * - identifying all file descriptors relating to control connections. |
503 | - * - clearing the close-on-exec flag on each file descriptor. |
504 | - * - storing all file descriptor values in the JSON. |
505 | - * |
506 | - * Returns: JSON object containing array of control connection details, |
507 | - * or NULL on error. |
508 | - **/ |
509 | -json_object * |
510 | -control_serialise_all (void) |
511 | -{ |
512 | - json_object *json; |
513 | - |
514 | - control_init (); |
515 | - |
516 | - json = json_object_new_array (); |
517 | - if (! json) |
518 | - return NULL; |
519 | - |
520 | - NIH_LIST_FOREACH (control_conns, iter) { |
521 | - NihListEntry *entry = (NihListEntry *)iter; |
522 | - DBusConnection *conn = entry->data; |
523 | - json_object *json_conn; |
524 | -#if 0 |
525 | - int fd; |
526 | - |
527 | - fd = control_get_connection_fd (conn); |
528 | - |
529 | - if (state_toggle_cloexec (fd, FALSE) < 0) { |
530 | - nih_error (_("Failed to clear control connection CLOEXEC flag")); |
531 | - goto error; |
532 | - } |
533 | -#else |
534 | - /* FIXME */ |
535 | - nih_warn ("XXX: WARNING (%s:%d): NOT clearing close-on-exec bit for D-Bus connections yet", |
536 | - __func__, __LINE__); |
537 | -#endif |
538 | - |
539 | - json_conn = control_serialise (conn); |
540 | - |
541 | - if (! json_conn) |
542 | - goto error; |
543 | - |
544 | - json_object_array_add (json, json_conn); |
545 | - } |
546 | - |
547 | - return json; |
548 | - |
549 | -error: |
550 | - json_object_put (json); |
551 | - return NULL; |
552 | -} |
553 | - |
554 | -/** |
555 | - * control_deserialise: |
556 | - * @json: JSON-serialised DBusConnection object to deserialise. |
557 | - * |
558 | - * Convert @json into a DBusConnection object. |
559 | - * |
560 | - * Returns: DBusConnection object, or NULL on error. |
561 | - **/ |
562 | -static DBusConnection * |
563 | -control_deserialise (json_object *json) |
564 | -{ |
565 | - DBusConnection *conn = NULL; |
566 | - DBusError error; |
567 | - int fd; |
568 | - nih_local char *address = NULL; |
569 | - NihListEntry *entry; |
570 | - |
571 | - nih_assert (json); |
572 | - |
573 | - if (! state_check_json_type (json, object)) |
574 | - return NULL; |
575 | - |
576 | - if (! state_get_json_int_var (json, "fd", fd)) |
577 | - goto error; |
578 | - |
579 | - if (! state_fd_valid (fd)) |
580 | - goto error; |
581 | - |
582 | - if (! state_get_json_string_var (json, "address", NULL, address)) |
583 | - goto error; |
584 | - |
585 | - dbus_error_init (&error); |
586 | - |
587 | - /* FIXME: this isn't currently possible as |
588 | - * dbus_connection_open_from_fd() has not been added to D-Bus. |
589 | - * |
590 | - * References: |
591 | - * |
592 | - * See: lp:~jamesodhunt/dbus/create-connection-from-fd |
593 | - */ |
594 | - |
595 | - /* (Re)create the D-Bus connections from the file descriptors |
596 | - * passed from the original PID 1. |
597 | - */ |
598 | - |
599 | -/* FIXME */ |
600 | -#if 0 |
601 | - nih_warn ("XXX: WARNING(%s:%d): using unofficial D-Bus API dbus_connection_open_from_fd()", |
602 | - __func__, __LINE__); |
603 | - |
604 | - conn = dbus_connection_open_from_fd (address, fd, &error); |
605 | - if (! conn || dbus_error_is_set (&error)) { |
606 | - nih_error ("%s: %s", |
607 | - _("failed to recreate D-Bus connection from fd"), |
608 | - error.message); |
609 | - dbus_error_free (&error); |
610 | - goto error; |
611 | - } |
612 | -#else |
613 | - nih_warn ("XXX: WARNING (%s:%d): unable to maintain D-Bus connections " |
614 | - "- bridges must be restarted", |
615 | - __func__, __LINE__); |
616 | - |
617 | - /* FIXME: keep compiler happy */ |
618 | - conn = NULL; |
619 | -#endif |
620 | - |
621 | - /* Re-apply close-on-exec flag to stop fd from leaking |
622 | - * to child processes. |
623 | - */ |
624 | - if (state_toggle_cloexec (fd, 1) < 0) |
625 | - goto error; |
626 | - |
627 | - /* Add the connection to the list */ |
628 | - entry = NIH_MUST (nih_list_entry_new (NULL)); |
629 | - |
630 | - entry->data = conn; |
631 | - |
632 | - nih_list_add (control_conns, &entry->entry); |
633 | - |
634 | - if (json_object_object_get_ex (json, "control_bus", NULL)) |
635 | - control_bus = conn; |
636 | - |
637 | - return conn; |
638 | - |
639 | -error: |
640 | - dbus_free (conn); |
641 | - return NULL; |
642 | -} |
643 | - |
644 | -/** |
645 | - * control_deserialise_all: |
646 | - * |
647 | - * @json: root of JSON-serialised state. |
648 | - * |
649 | - * Convert JSON representation of control connections back into |
650 | - * DBusConnection objects. |
651 | - * |
652 | - * Returns: 0 on success, -1 on error. |
653 | - **/ |
654 | -int |
655 | -control_deserialise_all (json_object *json) |
656 | -{ |
657 | - nih_assert (json); |
658 | - |
659 | - control_init (); |
660 | - |
661 | - nih_assert (! control_bus); |
662 | - nih_assert (NIH_LIST_EMPTY (control_conns)); |
663 | - |
664 | - json_control_conns = json_object_object_get (json, "control_conns"); |
665 | - |
666 | - if (! json_control_conns) |
667 | - goto error; |
668 | - |
669 | - if (! state_check_json_type (json_control_conns, array)) |
670 | - goto error; |
671 | - |
672 | - for (int i = 0; i < json_object_array_length (json_control_conns); i++) { |
673 | - json_object *json_control_conn; |
674 | - |
675 | - json_control_conn = json_object_array_get_idx (json_control_conns, i); |
676 | - if (! json_control_conn) |
677 | - goto error; |
678 | - |
679 | - /* FIXME */ |
680 | -#if 0 |
681 | - if (! control_deserialise (json_control_conn)) |
682 | - goto error; |
683 | -#else |
684 | - nih_warn ("XXX: WARNING (%s:%d): D-Bus connections NOT being deserialised yet", |
685 | - __func__, __LINE__); |
686 | -#endif |
687 | - } |
688 | - |
689 | -#if 0 |
690 | - if (! control_bus) |
691 | - goto error; |
692 | -#endif |
693 | - |
694 | - return 0; |
695 | - |
696 | -error: |
697 | - return -1; |
698 | - |
699 | -} |
700 | +} |
701 | + |
702 | |
703 | /** |
704 | * control_conn_to_index: |
705 | @@ -1314,7 +933,8 @@ |
706 | DBusError error; |
707 | int ret; |
708 | |
709 | - nih_assert (control_bus); |
710 | + if (! control_bus) |
711 | + return 0; |
712 | |
713 | dbus_error_init (&error); |
714 | ret = dbus_bus_release_name (control_bus, |
715 | @@ -1328,77 +948,3 @@ |
716 | |
717 | return 0; |
718 | } |
719 | - |
720 | - |
721 | -/* FIXME: TEST/DEBUG only */ |
722 | -#if 1 |
723 | -/** |
724 | - * control_debug_serialise: |
725 | - * |
726 | - * @data: not used, |
727 | - * @message: D-Bus connection and message received, |
728 | - * @json: output string returned to client. |
729 | - * |
730 | - * Convert internal state to JSON string. |
731 | - * |
732 | - * Returns: zero on success, negative value on raised error. |
733 | - **/ |
734 | -int |
735 | -control_debug_serialise (void *data, |
736 | - NihDBusMessage *message, |
737 | - char **json) |
738 | -{ |
739 | - size_t len; |
740 | - |
741 | - nih_assert (message != NULL); |
742 | - nih_assert (json != NULL); |
743 | - |
744 | - control_prepare_reexec (); |
745 | - |
746 | - if (state_to_string (json, &len) < 0) |
747 | - goto error; |
748 | - |
749 | - nih_ref (*json, message); |
750 | - |
751 | - return 0; |
752 | - |
753 | -error: |
754 | - nih_dbus_error_raise_printf (DBUS_ERROR_NO_MEMORY, |
755 | - _("Out of Memory")); |
756 | - return -1; |
757 | -} |
758 | - |
759 | -/** |
760 | - * control_debug_deserialise: |
761 | - * |
762 | - * @data: not used, |
763 | - * @message: D-Bus connection and message received, |
764 | - * @json: JSON string to be deserialised. |
765 | - * |
766 | - * Convert JSON string to internal state. |
767 | - * |
768 | - * Returns: zero on success, negative value on raised error. |
769 | - **/ |
770 | -int |
771 | -control_debug_deserialise (void *data, |
772 | - NihDBusMessage *message, |
773 | - char *json) |
774 | -{ |
775 | - int ret; |
776 | - nih_assert (message != NULL); |
777 | - nih_assert (json != NULL); |
778 | - |
779 | - ret = state_from_string (json); |
780 | - |
781 | - if (ret < 0) |
782 | - goto error; |
783 | - |
784 | - return 0; |
785 | - |
786 | -error: |
787 | - nih_dbus_error_raise_printf (DBUS_ERROR_NO_MEMORY, |
788 | - _("Out of Memory")); |
789 | - return -1; |
790 | -} |
791 | - |
792 | -#endif |
793 | |
794 | === modified file 'init/control.h' |
795 | --- init/control.h 2012-08-24 17:38:22 +0000 |
796 | +++ init/control.h 2012-09-11 00:41:22 +0000 |
797 | @@ -56,7 +56,7 @@ |
798 | __attribute__ ((warn_unused_result)); |
799 | void control_server_close (void); |
800 | |
801 | -int control_bus_open (int restart) |
802 | +int control_bus_open (void) |
803 | __attribute__ ((warn_unused_result)); |
804 | void control_bus_close (void); |
805 | |
806 | @@ -94,12 +94,6 @@ |
807 | |
808 | void control_prepare_reexec (void); |
809 | |
810 | -json_object * control_serialise_all (void) |
811 | - __attribute__ ((malloc, warn_unused_result)); |
812 | - |
813 | -int control_deserialise_all (json_object *json) |
814 | - __attribute__ ((warn_unused_result)); |
815 | - |
816 | int control_conn_to_index (const DBusConnection *connection) |
817 | __attribute__ ((warn_unused_result)); |
818 | |
819 | @@ -110,21 +104,6 @@ |
820 | int control_bus_release_name (void) |
821 | __attribute__ ((warn_unused_result)); |
822 | |
823 | -/* FIXME: DEBUG/TEST only */ |
824 | -#if 1 |
825 | -int |
826 | -control_debug_serialise (void *data, |
827 | - NihDBusMessage *message, |
828 | - char **json) |
829 | - __attribute__ ((warn_unused_result)); |
830 | - |
831 | -int |
832 | -control_debug_deserialise (void *data, |
833 | - NihDBusMessage *message, |
834 | - char *json) |
835 | - __attribute__ ((warn_unused_result)); |
836 | -#endif |
837 | - |
838 | NIH_END_EXTERN |
839 | |
840 | #endif /* INIT_CONTROL_H */ |
841 | |
842 | === modified file 'init/errors.h' |
843 | --- init/errors.h 2012-08-23 17:01:48 +0000 |
844 | +++ init/errors.h 2012-09-11 00:41:22 +0000 |
845 | @@ -54,7 +54,6 @@ |
846 | |
847 | /* Errors while handling control requests */ |
848 | CONTROL_NAME_TAKEN, |
849 | - CONTROL_REEXEC_ERROR, |
850 | }; |
851 | |
852 | /* Error strings for defined messages */ |
853 | @@ -77,6 +76,5 @@ |
854 | #define PARSE_EXPECTED_VARIABLE_STR N_("Expected variable name before value") |
855 | #define PARSE_MISMATCHED_PARENS_STR N_("Mismatched parentheses") |
856 | #define CONTROL_NAME_TAKEN_STR N_("Name already taken") |
857 | -#define CONTROL_REEXEC_ERROR_STR N_("No existing control bus") |
858 | |
859 | #endif /* INIT_ERRORS_H */ |
860 | |
861 | === modified file 'init/event.c' |
862 | --- init/event.c 2012-08-17 16:05:54 +0000 |
863 | +++ init/event.c 2012-09-11 00:41:22 +0000 |
864 | @@ -46,6 +46,7 @@ |
865 | |
866 | #include "com.ubuntu.Upstart.h" |
867 | |
868 | + |
869 | /* Prototypes for static functions */ |
870 | static void event_pending (Event *event); |
871 | static void event_pending_handle_jobs (Event *event); |
872 | @@ -539,8 +540,6 @@ |
873 | nih_assert (event); |
874 | nih_assert (event->name); |
875 | |
876 | - event_init (); |
877 | - |
878 | json = json_object_new_object (); |
879 | if (! json) |
880 | return NULL; |
881 | @@ -572,9 +571,6 @@ |
882 | if (! state_set_json_int_var_from_obj (json, event, blockers)) |
883 | goto error; |
884 | |
885 | - /* FIXME: should we remove the if test and always encode |
886 | - * something in the JSON here? |
887 | - */ |
888 | if (! NIH_LIST_EMPTY (&event->blocking)) { |
889 | json_object *json_blocking; |
890 | |
891 | @@ -633,20 +629,22 @@ |
892 | * event_deserialise: |
893 | * @json: JSON-serialised Event object to deserialise. |
894 | * |
895 | - * Convert @json into a partial Event object. |
896 | + * Convert @json into an Event object. |
897 | * |
898 | * Note that the object returned is not a true Event since not all |
899 | * structure elements are encoded in the JSON. Of particular note are |
900 | * that event->blocking and event->blockers are handled by |
901 | * state_serialise_resolve_deps(). |
902 | * |
903 | - * Returns: partial Event object, or NULL on error. |
904 | + * Returns: Event object, or NULL on error. |
905 | **/ |
906 | static Event * |
907 | event_deserialise (json_object *json) |
908 | { |
909 | json_object *json_env; |
910 | - Event *partial; |
911 | + Event *event; |
912 | + nih_local char *name; |
913 | + char **env; |
914 | int session_index; |
915 | |
916 | nih_assert (json); |
917 | @@ -654,43 +652,41 @@ |
918 | if (! state_check_json_type (json, object)) |
919 | return NULL; |
920 | |
921 | - partial = nih_new (NULL, Event); |
922 | - if (! partial) |
923 | + if (! state_get_json_string_var (json, "name", NULL, name)) |
924 | + goto error; |
925 | + |
926 | + if (! state_get_json_var_full (json, "env", array, json_env)) |
927 | + goto error; |
928 | + |
929 | + env = state_deserialise_str_array (NULL, json_env, TRUE); |
930 | + if (! env) |
931 | + goto error; |
932 | + |
933 | + event = event_new (NULL, name, env); |
934 | + if (! event) |
935 | return NULL; |
936 | |
937 | - memset (partial, '\0', sizeof (Event)); |
938 | - |
939 | - if (! state_get_json_string_var_to_obj (json, partial, name)) |
940 | - goto error; |
941 | - |
942 | - if (! state_get_json_int_var_to_obj (json, partial, fd)) |
943 | + if (! state_get_json_int_var_to_obj (json, event, fd)) |
944 | goto error; |
945 | |
946 | if (! state_get_json_int_var (json, "session", session_index)) |
947 | goto error; |
948 | |
949 | /* can't check return value here (as all values are legitimate) */ |
950 | - partial->session = session_from_index (session_index); |
951 | - |
952 | - if (! state_get_json_var_full (json, "env", array, json_env)) |
953 | - goto error; |
954 | - |
955 | - partial->env = state_deserialise_str_array (partial, json_env, TRUE); |
956 | - if (! partial->env) |
957 | - goto error; |
958 | + event->session = session_from_index (session_index); |
959 | |
960 | if (! state_get_json_enum_var (json, |
961 | event_progress_str_to_enum, |
962 | - "progress", partial->progress)) |
963 | - goto error; |
964 | - |
965 | - if (! state_set_json_int_var_from_obj (json, partial, failed)) |
966 | - goto error; |
967 | - |
968 | - return partial; |
969 | + "progress", event->progress)) |
970 | + goto error; |
971 | + |
972 | + if (! state_set_json_int_var_from_obj (json, event, failed)) |
973 | + goto error; |
974 | + |
975 | + return event; |
976 | |
977 | error: |
978 | - nih_free (partial); |
979 | + nih_free (event); |
980 | return NULL; |
981 | } |
982 | |
983 | @@ -706,19 +702,13 @@ |
984 | int |
985 | event_deserialise_all (json_object *json) |
986 | { |
987 | - nih_local Event *partial = NULL; |
988 | Event *event; |
989 | |
990 | nih_assert (json); |
991 | |
992 | event_init (); |
993 | |
994 | - /* FIXME: enable for final build */ |
995 | -#if PRODUCTION_BUILD |
996 | nih_assert (NIH_LIST_EMPTY (events)); |
997 | -#else |
998 | - nih_warn ("XXX: WARNING (%s:%d): NIH_LIST_EMPTY(events) check disabled", __func__, __LINE__); |
999 | -#endif |
1000 | json_events = json_object_object_get (json, "events"); |
1001 | |
1002 | if (! json_events) |
1003 | @@ -737,14 +727,9 @@ |
1004 | if (! state_check_json_type (json_event, object)) |
1005 | goto error; |
1006 | |
1007 | - partial = event_deserialise (json_event); |
1008 | - if (! partial) |
1009 | + event = event_deserialise (json_event); |
1010 | + if (! event) |
1011 | goto error; |
1012 | - |
1013 | - /* Create a new event */ |
1014 | - event = NIH_MUST (event_new (NULL, partial->name, partial->env)); |
1015 | - |
1016 | - event->session = partial->session; |
1017 | } |
1018 | |
1019 | return 0; |
1020 | @@ -809,7 +794,7 @@ |
1021 | int found = FALSE; |
1022 | |
1023 | nih_assert (event); |
1024 | - nih_assert (events); |
1025 | + event_init (); |
1026 | |
1027 | NIH_LIST_FOREACH (events, iter) { |
1028 | Event *tmp = (Event *)iter; |
1029 | @@ -843,7 +828,7 @@ |
1030 | int i = 0; |
1031 | |
1032 | nih_assert (event_index >= 0); |
1033 | - nih_assert (events); |
1034 | + event_init (); |
1035 | |
1036 | NIH_LIST_FOREACH (events, iter) { |
1037 | Event *event = (Event *)iter; |
1038 | |
1039 | === modified file 'init/event_operator.c' |
1040 | --- init/event_operator.c 2012-08-31 14:42:40 +0000 |
1041 | +++ init/event_operator.c 2012-09-11 00:41:22 +0000 |
1042 | @@ -725,7 +725,7 @@ |
1043 | event_operator_collapse (EventOperator *condition) |
1044 | { |
1045 | nih_local NihList *stack = NULL; |
1046 | - nih_local NihListEntry *latest = NULL; |
1047 | + NihListEntry *latest = NULL; |
1048 | NihTree *root; |
1049 | |
1050 | nih_assert (condition); |
1051 | |
1052 | === modified file 'init/job.c' |
1053 | --- init/job.c 2012-08-28 16:29:50 +0000 |
1054 | +++ init/job.c 2012-09-11 00:41:22 +0000 |
1055 | @@ -63,7 +63,7 @@ |
1056 | |
1057 | /* Prototypes for static functions */ |
1058 | static json_object *job_serialise (const Job *job); |
1059 | -static Job *job_deserialise (json_object *json); |
1060 | +static Job *job_deserialise (JobClass *parent, json_object *json); |
1061 | |
1062 | static const char * |
1063 | job_goal_enum_to_str (JobGoal goal) |
1064 | @@ -93,7 +93,7 @@ |
1065 | __attribute__ ((malloc, warn_unused_result)); |
1066 | |
1067 | static NihTimer * |
1068 | -job_deserialise_kill_timer (void *parent, json_object *json) |
1069 | +job_deserialise_kill_timer (json_object *json) |
1070 | __attribute__ ((malloc, warn_unused_result)); |
1071 | |
1072 | /** |
1073 | @@ -155,6 +155,7 @@ |
1074 | job->stop_env = NULL; |
1075 | |
1076 | job->stop_on = NULL; |
1077 | + |
1078 | if (class->stop_on) { |
1079 | job->stop_on = event_operator_copy (job, class->stop_on); |
1080 | if (! job->stop_on) |
1081 | @@ -1553,11 +1554,6 @@ |
1082 | |
1083 | nih_assert (job); |
1084 | |
1085 | - /* FIXME: |
1086 | - * |
1087 | - * log !!! |
1088 | - */ |
1089 | - |
1090 | json = json_object_new_object (); |
1091 | if (! json) |
1092 | return NULL; |
1093 | @@ -1587,15 +1583,15 @@ |
1094 | if (! state_set_json_str_array_from_obj (json, job, stop_env)) |
1095 | goto error; |
1096 | |
1097 | - stop_on = job->stop_on |
1098 | - ? event_operator_collapse (job->stop_on) |
1099 | - : NIH_MUST (nih_strdup (NULL, "")); |
1100 | - |
1101 | - if (! stop_on) |
1102 | - goto error; |
1103 | - |
1104 | - if (! state_set_json_string_var (json, "stop_on", stop_on)) |
1105 | - goto error; |
1106 | + if (job->stop_on) |
1107 | + { |
1108 | + stop_on = event_operator_collapse (job->stop_on); |
1109 | + if (! stop_on) |
1110 | + goto error; |
1111 | + |
1112 | + if (! state_set_json_string_var (json, "stop_on", stop_on)) |
1113 | + goto error; |
1114 | + } |
1115 | |
1116 | json_fds = state_serialise_int_array (int, job->fds, job->num_fds); |
1117 | if (! json_fds) |
1118 | @@ -1611,11 +1607,8 @@ |
1119 | json_object_object_add (json, "pid", json_pid); |
1120 | |
1121 | /* Encode the blocking event as an index number which represents |
1122 | - * the events position in the JSON events array. |
1123 | + * the event's position in the JSON events array. |
1124 | */ |
1125 | -#if 1 |
1126 | - /* FIXME: we're only encoding if there *IS* a blocker!?! */ |
1127 | -#endif |
1128 | if (job->blocker) { |
1129 | int event_index; |
1130 | |
1131 | @@ -1633,9 +1626,6 @@ |
1132 | |
1133 | } |
1134 | |
1135 | - /* FIXME: should we remove the if test and always encode |
1136 | - * something in the JSON here? |
1137 | - */ |
1138 | if (! NIH_LIST_EMPTY (&job->blocking)) { |
1139 | json_object *json_blocking; |
1140 | |
1141 | @@ -1646,11 +1636,6 @@ |
1142 | json_object_object_add (json, "blocking", json_blocking); |
1143 | } |
1144 | |
1145 | - /* FIXME */ |
1146 | -#if 1 |
1147 | - nih_info ("XXX:%s:%d:warning job->kill_timer NEEDS TESTING", __func__, __LINE__); |
1148 | -#endif |
1149 | - |
1150 | /* conditionally encode kill timer */ |
1151 | if (job->kill_timer) { |
1152 | json_object *kill_timer; |
1153 | @@ -1689,7 +1674,6 @@ |
1154 | goto error; |
1155 | |
1156 | /* FIXME: handle ptraced jobs across re-exec */ |
1157 | -#if 1 |
1158 | if (job->trace_state != TRACE_NONE) { |
1159 | nih_info ("XXX: WARNING (%s:%d) tracking of ptraced job instance '%s' (class '%s') will stop after re-exec", |
1160 | __func__, __LINE__, |
1161 | @@ -1707,7 +1691,6 @@ |
1162 | i, job->pid[i]); |
1163 | } |
1164 | } |
1165 | -#endif |
1166 | |
1167 | if (! state_set_json_enum_var (json, |
1168 | job_trace_state_enum_to_str, |
1169 | @@ -1717,12 +1700,12 @@ |
1170 | json_logs = json_object_new_array (); |
1171 | |
1172 | if (! json_logs) |
1173 | - goto error; |
1174 | + return json; |
1175 | |
1176 | - for (int i = 0; i < PROCESS_LAST; i++) { |
1177 | + for (int process = 0; process < PROCESS_LAST; process++) { |
1178 | json_object *json_log; |
1179 | |
1180 | - json_log = log_serialise (job->log[i]); |
1181 | + json_log = log_serialise (job->log[process]); |
1182 | if (! json_log) |
1183 | goto error; |
1184 | |
1185 | @@ -1732,10 +1715,6 @@ |
1186 | |
1187 | json_object_object_add (json, "log", json_logs); |
1188 | |
1189 | -#if 1 |
1190 | - nih_info ("XXX: WARNING (%s:%d) job->log NOT fully handled yet", __func__, __LINE__); |
1191 | -#endif |
1192 | - |
1193 | return json; |
1194 | |
1195 | error: |
1196 | @@ -1753,6 +1732,7 @@ |
1197 | json_object * |
1198 | job_serialise_all (const NihHash *jobs) |
1199 | { |
1200 | + int count = 0; |
1201 | json_object *json; |
1202 | |
1203 | nih_assert (jobs); |
1204 | @@ -1765,6 +1745,7 @@ |
1205 | json_object *json_job; |
1206 | Job *job = (Job *)iter; |
1207 | |
1208 | + count++; |
1209 | json_job = job_serialise (job); |
1210 | |
1211 | if (! json_job) |
1212 | @@ -1773,6 +1754,12 @@ |
1213 | json_object_array_add (json, json_job); |
1214 | } |
1215 | |
1216 | + /* Raise an error to avoid serialising job classes with |
1217 | + * no associated jobs. |
1218 | + */ |
1219 | + if (!count) |
1220 | + goto error; |
1221 | + |
1222 | return json; |
1223 | |
1224 | error: |
1225 | @@ -1782,58 +1769,60 @@ |
1226 | |
1227 | /** |
1228 | * job_deserialise: |
1229 | + * @parent: job class for JSON-encoded jobs, |
1230 | * @json: JSON-serialised Job object to deserialise. |
1231 | * |
1232 | - * Note that the object returned is not a true Job since not all |
1233 | - * structure elements are encoded in the JSON. Of particular note are |
1234 | - * that job->blocking is handled by state_serialise_resolve_deps(). |
1235 | - * |
1236 | * XXX: All events must have been deserialised prior to this function |
1237 | * XXX: being called. |
1238 | * |
1239 | - * Returns: partial Job object, or NULL on error. |
1240 | + * Returns: Job object, or NULL on error. |
1241 | **/ |
1242 | static Job * |
1243 | -job_deserialise (json_object *json) |
1244 | +job_deserialise (JobClass *parent, json_object *json) |
1245 | { |
1246 | - Job *partial; |
1247 | - json_object *kill_timer; |
1248 | - json_object *blocker; |
1249 | + nih_local char *name = NULL; |
1250 | + Job *job; |
1251 | + json_object *json_kill_timer; |
1252 | + json_object *blocker; |
1253 | + json_object *json_fds; |
1254 | + json_object *json_pid; |
1255 | + json_object *json_logs; |
1256 | + size_t len; |
1257 | + int ret; |
1258 | |
1259 | nih_assert (json); |
1260 | |
1261 | if (! state_check_json_type (json, object)) |
1262 | return NULL; |
1263 | |
1264 | - partial = nih_new (NULL, Job); |
1265 | - if (! partial) |
1266 | + if (! state_get_json_string_var (json, "name", NULL, name)) |
1267 | + goto error; |
1268 | + |
1269 | + job = NIH_MUST (job_new (parent, name)); |
1270 | + |
1271 | + if (! job) |
1272 | return NULL; |
1273 | |
1274 | - memset (partial, '\0', sizeof (Job)); |
1275 | - |
1276 | - if (! state_get_json_string_var_to_obj (json, partial, name)) |
1277 | - goto error; |
1278 | - |
1279 | - if (! state_get_json_string_var_to_obj (json, partial, path)) |
1280 | + if (! state_get_json_string_var_to_obj (json, job, path)) |
1281 | goto error; |
1282 | |
1283 | if (! state_get_json_enum_var (json, |
1284 | job_goal_str_to_enum, |
1285 | - "goal", partial->goal)) |
1286 | + "goal", job->goal)) |
1287 | goto error; |
1288 | |
1289 | if (! state_get_json_enum_var (json, |
1290 | job_state_str_to_enum, |
1291 | - "state", partial->state)) |
1292 | - goto error; |
1293 | - |
1294 | - if (! state_get_json_env_array_to_obj (json, partial, env)) |
1295 | - goto error; |
1296 | - |
1297 | - if (! state_get_json_env_array_to_obj (json, partial, start_env)) |
1298 | - goto error; |
1299 | - |
1300 | - if (! state_get_json_env_array_to_obj (json, partial, stop_env)) |
1301 | + "state", job->state)) |
1302 | + goto error; |
1303 | + |
1304 | + if (! state_get_json_env_array_to_obj (json, job, env)) |
1305 | + goto error; |
1306 | + |
1307 | + if (! state_get_json_env_array_to_obj (json, job, start_env)) |
1308 | + goto error; |
1309 | + |
1310 | + if (! state_get_json_env_array_to_obj (json, job, stop_env)) |
1311 | goto error; |
1312 | |
1313 | if (json_object_object_get (json, "stop_on")) { |
1314 | @@ -1863,8 +1852,9 @@ |
1315 | goto error; |
1316 | } |
1317 | |
1318 | - partial->stop_on = event_operator_copy (partial, tmp->stop_on); |
1319 | - if (! partial->stop_on) |
1320 | + nih_free (job->stop_on); |
1321 | + job->stop_on = event_operator_copy (job, tmp->stop_on); |
1322 | + if (! job->stop_on) |
1323 | goto error; |
1324 | } |
1325 | } |
1326 | @@ -1881,68 +1871,122 @@ |
1327 | |
1328 | if (! state_get_json_int_var (json, "blocker", event_index)) |
1329 | goto error; |
1330 | - partial->blocker = event_from_index (event_index); |
1331 | + job->blocker = event_from_index (event_index); |
1332 | |
1333 | - if (! partial->blocker) |
1334 | + if (! job->blocker) |
1335 | goto error; |
1336 | } |
1337 | |
1338 | -#if 1 |
1339 | + if (! state_get_json_enum_var (json, |
1340 | + process_type_str_to_enum, |
1341 | + "kill_process", job->kill_process)) |
1342 | + goto error; |
1343 | + |
1344 | /* FIXME: kill_timer */ |
1345 | nih_info ("XXX: WARNING (%s:%d) job->kill_timer needs testing", __func__, __LINE__); |
1346 | -#endif |
1347 | /* Check to see if a kill timer exists first since we do not |
1348 | * want to end up creating a real but empty timer. |
1349 | */ |
1350 | - kill_timer = json_object_object_get (json, "kill_timer"); |
1351 | + json_kill_timer = json_object_object_get (json, "kill_timer"); |
1352 | |
1353 | - if (kill_timer) { |
1354 | - partial->kill_timer = job_deserialise_kill_timer (partial, json); |
1355 | - if (! partial->kill_timer) |
1356 | + if (json_kill_timer) { |
1357 | + /* Found a partial kill timer, so create a new one and |
1358 | + * adjust its due time. By the time the main loop gets |
1359 | + * called, the due time will probably be in the past |
1360 | + * such that the job will be stopped. |
1361 | + * |
1362 | + * To be completely fair we should: |
1363 | + * |
1364 | + * - encode the time at the point of serialisation in a |
1365 | + * JSON 'meta' header. |
1366 | + * - query the time post-deserialisation and calculate |
1367 | + * the delta (being the time to perform the stateful |
1368 | + * re-exec). |
1369 | + * - add that time to all jobs with active kill timers |
1370 | + * to give their processes the full amount of time to |
1371 | + * end. |
1372 | + */ |
1373 | + nih_local NihTimer *kill_timer = job_deserialise_kill_timer (json_kill_timer); |
1374 | + if (! kill_timer) |
1375 | goto error; |
1376 | - } else { |
1377 | - partial->kill_timer = NULL; |
1378 | + |
1379 | + nih_assert (job->kill_process); |
1380 | + job_process_set_kill_timer (job, job->kill_process, |
1381 | + kill_timer->timeout); |
1382 | + job_process_adj_kill_timer (job, kill_timer->due); |
1383 | } |
1384 | |
1385 | - if (! state_get_json_enum_var (json, |
1386 | - process_type_str_to_enum, |
1387 | - "kill_process", partial->kill_process)) |
1388 | - goto error; |
1389 | - |
1390 | - if (! state_get_json_int_var_to_obj (json, partial, failed)) |
1391 | - goto error; |
1392 | - |
1393 | - if (! state_get_json_enum_var (json, |
1394 | - process_type_str_to_enum, |
1395 | - "failed_process", partial->failed_process)) |
1396 | - goto error; |
1397 | - |
1398 | - if (! state_get_json_int_var_to_obj (json, partial, exit_status)) |
1399 | - goto error; |
1400 | - |
1401 | - if (! state_get_json_int_var_to_obj (json, partial, respawn_time)) |
1402 | - goto error; |
1403 | - |
1404 | - if (! state_get_json_int_var_to_obj (json, partial, respawn_count)) |
1405 | - goto error; |
1406 | - |
1407 | - if (! state_get_json_int_var_to_obj (json, partial, trace_forks)) |
1408 | + if (! state_get_json_int_var_to_obj (json, job, failed)) |
1409 | + goto error; |
1410 | + |
1411 | + if (! state_get_json_enum_var (json, |
1412 | + process_type_str_to_enum, |
1413 | + "failed_process", job->failed_process)) |
1414 | + goto error; |
1415 | + |
1416 | + if (! state_get_json_int_var_to_obj (json, job, exit_status)) |
1417 | + goto error; |
1418 | + |
1419 | + if (! state_get_json_int_var_to_obj (json, job, respawn_time)) |
1420 | + goto error; |
1421 | + |
1422 | + if (! state_get_json_int_var_to_obj (json, job, respawn_count)) |
1423 | + goto error; |
1424 | + |
1425 | + json_fds = json_object_object_get (json, "fds"); |
1426 | + if (! json_fds) |
1427 | + goto error; |
1428 | + |
1429 | + ret = state_deserialise_int_array (job, json_fds, |
1430 | + int, &job->fds, &job->num_fds); |
1431 | + if (ret < 0) |
1432 | + goto error; |
1433 | + |
1434 | + json_pid = json_object_object_get (json, "pid"); |
1435 | + if (! json_pid) |
1436 | + goto error; |
1437 | + |
1438 | + ret = state_deserialise_int_array (job, json_pid, |
1439 | + pid_t, &job->pid, &len); |
1440 | + if (ret < 0) |
1441 | + goto error; |
1442 | + |
1443 | + if (len != PROCESS_LAST) |
1444 | + goto error; |
1445 | + |
1446 | + if (! state_get_json_int_var_to_obj (json, job, trace_forks)) |
1447 | goto error; |
1448 | |
1449 | if (! state_get_json_enum_var (json, |
1450 | job_trace_state_str_to_enum, |
1451 | - "trace_state", partial->trace_state)) |
1452 | - goto error; |
1453 | - |
1454 | - /* FIXME: log!! */ |
1455 | -#if 1 |
1456 | - nih_info ("XXX: WARNING (%s:%d) job->log NOT handled", __func__, __LINE__); |
1457 | -#endif |
1458 | - |
1459 | - return partial; |
1460 | + "trace_state", job->trace_state)) |
1461 | + goto error; |
1462 | + |
1463 | + json_logs = json_object_object_get (json, "log"); |
1464 | + |
1465 | + if (! json_logs) |
1466 | + goto error; |
1467 | + |
1468 | + if (! state_check_json_type (json_logs, array)) |
1469 | + goto error; |
1470 | + |
1471 | + for (int process = 0; process < PROCESS_LAST; process++) { |
1472 | + json_object *json_log; |
1473 | + |
1474 | + json_log = json_object_array_get_idx (json_logs, process); |
1475 | + if (! json_log) |
1476 | + goto error; |
1477 | + |
1478 | + /* NULL if there was no log configured, or we failed to |
1479 | + * deserialise it; either way, this should be non-fatal. |
1480 | + */ |
1481 | + job->log[process] = log_deserialise (job->log, json_log); |
1482 | + } |
1483 | + |
1484 | + return job; |
1485 | |
1486 | error: |
1487 | - nih_free (partial); |
1488 | + nih_free (job); |
1489 | return NULL; |
1490 | } |
1491 | |
1492 | @@ -1961,11 +2005,7 @@ |
1493 | job_deserialise_all (JobClass *parent, json_object *json) |
1494 | { |
1495 | json_object *json_jobs; |
1496 | - json_object *json_fds; |
1497 | - json_object *json_pid; |
1498 | Job *job; |
1499 | - size_t len; |
1500 | - int ret; |
1501 | |
1502 | nih_assert (parent); |
1503 | nih_assert (json); |
1504 | @@ -1978,14 +2018,8 @@ |
1505 | if (! state_check_json_type (json_jobs, array)) |
1506 | goto error; |
1507 | |
1508 | - /* FIXME: finish!! |
1509 | - * |
1510 | - * - log!! |
1511 | - */ |
1512 | - |
1513 | for (int i = 0; i < json_object_array_length (json_jobs); i++) { |
1514 | json_object *json_job; |
1515 | - nih_local Job *partial = NULL; |
1516 | |
1517 | json_job = json_object_array_get_idx (json_jobs, i); |
1518 | if (! json_job) |
1519 | @@ -1994,100 +2028,9 @@ |
1520 | if (! state_check_json_type (json_job, object)) |
1521 | goto error; |
1522 | |
1523 | - partial = job_deserialise (json_job); |
1524 | - if (! partial) |
1525 | - goto error; |
1526 | - |
1527 | - job = NIH_MUST (job_new (parent, partial->name)); |
1528 | - |
1529 | - state_partial_copy_int (job, partial, goal); |
1530 | - state_partial_copy_int (job, partial, state); |
1531 | - |
1532 | - if (! state_copy_str_array_to_obj (job, partial, env)) |
1533 | - goto error; |
1534 | - |
1535 | - if (! state_copy_str_array_to_obj (job, partial, start_env)) |
1536 | - goto error; |
1537 | - if (! state_copy_str_array_to_obj (job, partial, stop_env)) |
1538 | - goto error; |
1539 | - |
1540 | - if (! state_copy_event_oper_to_obj (job, partial, stop_on)) |
1541 | - goto error; |
1542 | - |
1543 | - json_fds = json_object_object_get (json_job, "fds"); |
1544 | - if (! json_fds) |
1545 | - goto error; |
1546 | - |
1547 | - ret = state_deserialise_int_array (job, json_fds, |
1548 | - int, &job->fds, &job->num_fds); |
1549 | - if (ret < 0) |
1550 | - goto error; |
1551 | - |
1552 | - json_pid = json_object_object_get (json_job, "pid"); |
1553 | - if (! json_pid) |
1554 | - goto error; |
1555 | - |
1556 | - ret = state_deserialise_int_array (job, json_pid, |
1557 | - pid_t, &job->pid, &len); |
1558 | - if (ret < 0) |
1559 | - goto error; |
1560 | - |
1561 | - if (len != PROCESS_LAST) |
1562 | - goto error; |
1563 | - |
1564 | - state_partial_copy_ptr (job, partial, blocker); |
1565 | - |
1566 | - /* 'blocking' handled by state_deserialise_blocking() */ |
1567 | - |
1568 | - state_partial_copy_int (job, partial, kill_process); |
1569 | - |
1570 | - /* Found a partial kill timer, so create a new one and |
1571 | - * adjust its due time. By the time the main loop gets |
1572 | - * called, the due time will probably be in the past |
1573 | - * such that the job will be stopped. |
1574 | - * |
1575 | - * To be completely fair we should: |
1576 | - * |
1577 | - * - encode the time at the point of serialisation in a |
1578 | - * JSON 'meta' header. |
1579 | - * - query the time post-deserialisation and calculate |
1580 | - * the delta (being the time to perform the stateful |
1581 | - * re-exec). |
1582 | - * - add that time to all jobs with active kill timers |
1583 | - * to give their processes the full amount of time to |
1584 | - * end. |
1585 | - */ |
1586 | - if (partial->kill_timer) { |
1587 | - nih_assert (job->kill_process); |
1588 | - job_process_set_kill_timer (job, |
1589 | - job->kill_process, |
1590 | - partial->kill_timer->timeout); |
1591 | - job_process_adj_kill_timer (job, |
1592 | - partial->kill_timer->due); |
1593 | - } |
1594 | - |
1595 | - state_partial_copy_int (job, partial, failed); |
1596 | - state_partial_copy_int (job, partial, failed_process); |
1597 | - state_partial_copy_int (job, partial, exit_status); |
1598 | - state_partial_copy_int (job, partial, respawn_time); |
1599 | - state_partial_copy_int (job, partial, respawn_count); |
1600 | - state_partial_copy_int (job, partial, trace_forks); |
1601 | - state_partial_copy_int (job, partial, trace_state); |
1602 | - |
1603 | - /* FIXME: handle ptraced jobs across re-exec */ |
1604 | -#if 1 |
1605 | - if (partial->trace_state != TRACE_NONE) { |
1606 | - nih_info ("XXX: WARNING (%s:%d) tracking of ptraced job instance '%s' (class '%s') will now stop", |
1607 | - __func__, __LINE__, |
1608 | - job->name ? job->name : "", |
1609 | - job->class->name); |
1610 | - } |
1611 | -#endif |
1612 | - |
1613 | - |
1614 | -#if 1 |
1615 | - /* FIXME: log!!! */ |
1616 | -#endif |
1617 | + job = job_deserialise (parent, json_job); |
1618 | + if (! job) |
1619 | + goto error; |
1620 | |
1621 | } |
1622 | |
1623 | @@ -2263,7 +2206,6 @@ |
1624 | /** |
1625 | * job_deserialise_kill_timer: |
1626 | * |
1627 | - * @parent: parent for timer. |
1628 | * @json: JSON representation of NihTimer. |
1629 | * |
1630 | * Deserialise @json back into an NihTimer. |
1631 | @@ -2271,14 +2213,13 @@ |
1632 | * Returns: NihTimer on NULL on error. |
1633 | **/ |
1634 | static NihTimer * |
1635 | -job_deserialise_kill_timer (void *parent, json_object *json) |
1636 | +job_deserialise_kill_timer (json_object *json) |
1637 | { |
1638 | NihTimer *timer; |
1639 | |
1640 | - nih_assert (parent); |
1641 | nih_assert (json); |
1642 | |
1643 | - timer = nih_new (parent, NihTimer); |
1644 | + timer = nih_new (NULL, NihTimer); |
1645 | if (! timer) |
1646 | return NULL; |
1647 | |
1648 | |
1649 | === modified file 'init/job_class.c' |
1650 | --- init/job_class.c 2012-08-29 18:44:25 +0000 |
1651 | +++ init/job_class.c 2012-09-11 00:41:22 +0000 |
1652 | @@ -1659,28 +1659,25 @@ |
1653 | goto error; |
1654 | json_object_object_add (json, "export", json_export); |
1655 | |
1656 | - /* set "start/stop on" in the JSON even if no condition specified. |
1657 | - */ |
1658 | -#if 1 |
1659 | - /* FIXME: shouldn't we just encode condition if it exists?? */ |
1660 | -#endif |
1661 | - start_on = class->start_on |
1662 | - ? event_operator_collapse (class->start_on) |
1663 | - : NIH_MUST (nih_strdup (NULL, "")); |
1664 | - if (! start_on) |
1665 | - goto error; |
1666 | - |
1667 | - if (! state_set_json_string_var (json, "start_on", start_on)) |
1668 | - goto error; |
1669 | - |
1670 | - stop_on = class->stop_on |
1671 | - ? event_operator_collapse (class->stop_on) |
1672 | - : NIH_MUST (nih_strdup (NULL, "")); |
1673 | - if (! stop_on) |
1674 | - goto error; |
1675 | - |
1676 | - if (! state_set_json_string_var (json, "stop_on", stop_on)) |
1677 | - goto error; |
1678 | + if (class->start_on) |
1679 | + { |
1680 | + start_on = event_operator_collapse (class->start_on); |
1681 | + if (! start_on) |
1682 | + goto error; |
1683 | + |
1684 | + if (! state_set_json_string_var (json, "start_on", start_on)) |
1685 | + goto error; |
1686 | + } |
1687 | + |
1688 | + if (class->stop_on) |
1689 | + { |
1690 | + stop_on = event_operator_collapse (class->stop_on); |
1691 | + if (! stop_on) |
1692 | + goto error; |
1693 | + |
1694 | + if (! state_set_json_string_var (json, "stop_on", stop_on)) |
1695 | + goto error; |
1696 | + } |
1697 | |
1698 | json_emits = class->emits |
1699 | ? state_serialise_str_array (class->emits) |
1700 | @@ -1798,38 +1795,34 @@ |
1701 | |
1702 | json_class = job_class_serialise (class); |
1703 | |
1704 | + /* No object returned means the class doesn't need to be |
1705 | + * serialised. Even if this is a real failure, it's always |
1706 | + * better to serialise as much of the state as possible. |
1707 | + */ |
1708 | if (! json_class) |
1709 | - goto error; |
1710 | + continue; |
1711 | |
1712 | json_object_array_add (json, json_class); |
1713 | } |
1714 | |
1715 | return json; |
1716 | - |
1717 | -error: |
1718 | - json_object_put (json); |
1719 | - return NULL; |
1720 | } |
1721 | |
1722 | /** |
1723 | * job_class_deserialise: |
1724 | * @json: JSON-serialised JobClass object to deserialise. |
1725 | * |
1726 | - * Note that the object returned is not a true JobClass since not all |
1727 | - * structure elements are encoded in the JSON. |
1728 | - * |
1729 | - * Further, note that limits, process, instances (jobs), and normalexit |
1730 | - * are NOT handled by this function - use state_rlimit_deserialise_all(), |
1731 | - * process_deserialise_all(), job_deserialise_all() and |
1732 | - * state_deserialise_int_array() respectively. |
1733 | - * |
1734 | - * Returns: partial JobClass object, or NULL on error. |
1735 | + * Returns: JobClass object, or NULL on error. |
1736 | **/ |
1737 | static JobClass * |
1738 | job_class_deserialise (json_object *json) |
1739 | { |
1740 | - JobClass *partial; |
1741 | + json_object *json_normalexit; |
1742 | + JobClass *class = NULL; |
1743 | int session_index; |
1744 | + int ret; |
1745 | + nih_local char *name = NULL; |
1746 | + nih_local char *path = NULL; |
1747 | |
1748 | nih_assert (json); |
1749 | nih_assert (job_classes); |
1750 | @@ -1837,47 +1830,47 @@ |
1751 | if (! state_check_json_type (json, object)) |
1752 | goto error; |
1753 | |
1754 | - partial = nih_new (NULL, JobClass); |
1755 | - if (! partial) |
1756 | - return NULL; |
1757 | - |
1758 | - memset (partial, '\0', sizeof (JobClass)); |
1759 | - |
1760 | - if (! state_get_json_string_var_to_obj (json, partial, name)) |
1761 | - goto error; |
1762 | - |
1763 | - if (! state_get_json_string_var_to_obj (json, partial, path)) |
1764 | - goto error; |
1765 | - |
1766 | if (! state_get_json_int_var (json, "session", session_index)) |
1767 | - goto error; |
1768 | - |
1769 | - /* can't check return value here (as all values are legitimate) */ |
1770 | - partial->session = session_from_index (session_index); |
1771 | - |
1772 | - if (partial->session != NULL) { |
1773 | + goto error; |
1774 | + |
1775 | + if (! state_get_json_string_var (json, "name", NULL, name)) |
1776 | + goto error; |
1777 | + |
1778 | + class = NIH_MUST (job_class_new (NULL, name, |
1779 | + session_from_index (session_index))); |
1780 | + if (! class) |
1781 | + goto error; |
1782 | + |
1783 | + if (class->session != NULL) { |
1784 | nih_warn ("XXX: WARNING (%s:%d): deserialisation of " |
1785 | "user jobs and chroot sessions not currently supported", |
1786 | __func__, __LINE__); |
1787 | goto error; |
1788 | } |
1789 | |
1790 | - if (! state_get_json_string_var_to_obj (json, partial, instance)) |
1791 | - goto error; |
1792 | - |
1793 | - if (! state_get_json_string_var_to_obj (json, partial, description)) |
1794 | - goto error; |
1795 | - |
1796 | - if (! state_get_json_string_var_to_obj (json, partial, author)) |
1797 | - goto error; |
1798 | - |
1799 | - if (! state_get_json_string_var_to_obj (json, partial, version)) |
1800 | - goto error; |
1801 | - |
1802 | - if (! state_get_json_env_array_to_obj (json, partial, env)) |
1803 | - goto error; |
1804 | - |
1805 | - if (! state_get_json_env_array_to_obj (json, partial, export)) |
1806 | + /* job_class_new() sets path */ |
1807 | + if (! state_get_json_string_var (json, "path", NULL, path)) |
1808 | + goto error; |
1809 | + |
1810 | + nih_assert (! strcmp (class->path, path)); |
1811 | + |
1812 | + nih_free (class->instance); |
1813 | + if (! state_get_json_string_var_to_obj (json, class, instance)) |
1814 | + goto error; |
1815 | + |
1816 | + if (! state_get_json_string_var_to_obj (json, class, description)) |
1817 | + goto error; |
1818 | + |
1819 | + if (! state_get_json_string_var_to_obj (json, class, author)) |
1820 | + goto error; |
1821 | + |
1822 | + if (! state_get_json_string_var_to_obj (json, class, version)) |
1823 | + goto error; |
1824 | + |
1825 | + if (! state_get_json_env_array_to_obj (json, class, env)) |
1826 | + goto error; |
1827 | + |
1828 | + if (! state_get_json_env_array_to_obj (json, class, export)) |
1829 | goto error; |
1830 | |
1831 | /* start and stop conditions are optional */ |
1832 | @@ -1888,8 +1881,8 @@ |
1833 | goto error; |
1834 | |
1835 | if (*start_on) { |
1836 | - partial->start_on = parse_on_simple (partial, "start", start_on); |
1837 | - if (! partial->start_on) { |
1838 | + class->start_on = parse_on_simple (class, "start", start_on); |
1839 | + if (! class->start_on) { |
1840 | NihError *err; |
1841 | |
1842 | err = nih_error_get (); |
1843 | @@ -1913,8 +1906,8 @@ |
1844 | goto error; |
1845 | |
1846 | if (*stop_on) { |
1847 | - partial->stop_on = parse_on_simple (partial, "stop", stop_on); |
1848 | - if (! partial->stop_on) { |
1849 | + class->stop_on = parse_on_simple (class, "stop", stop_on); |
1850 | + if (! class->stop_on) { |
1851 | NihError *err; |
1852 | |
1853 | err = nih_error_get (); |
1854 | @@ -1931,75 +1924,102 @@ |
1855 | } |
1856 | } |
1857 | |
1858 | - if (! state_get_json_str_array_to_obj (json, partial, emits)) |
1859 | + if (! state_get_json_str_array_to_obj (json, class, emits)) |
1860 | goto error; |
1861 | |
1862 | /* 'process' must be handled by caller */ |
1863 | |
1864 | if (! state_get_json_enum_var (json, |
1865 | job_class_expect_type_str_to_enum, |
1866 | - "expect", partial->expect)) |
1867 | + "expect", class->expect)) |
1868 | goto error; |
1869 | |
1870 | - if (! state_get_json_int_var_to_obj (json, partial, task)) |
1871 | - goto error; |
1872 | - |
1873 | - if (! state_get_json_int_var_to_obj (json, partial, kill_timeout)) |
1874 | - goto error; |
1875 | - |
1876 | - if (! state_get_json_int_var_to_obj (json, partial, kill_signal)) |
1877 | - goto error; |
1878 | - |
1879 | - if (! state_get_json_int_var_to_obj (json, partial, respawn)) |
1880 | - goto error; |
1881 | - |
1882 | - if (! state_get_json_int_var_to_obj (json, partial, respawn_limit)) |
1883 | - goto error; |
1884 | - |
1885 | - if (! state_get_json_int_var_to_obj (json, partial, respawn_interval)) |
1886 | - goto error; |
1887 | - |
1888 | - /* normalexit and normalexit_len handled by caller */ |
1889 | + if (! state_get_json_int_var_to_obj (json, class, task)) |
1890 | + goto error; |
1891 | + |
1892 | + if (! state_get_json_int_var_to_obj (json, class, kill_timeout)) |
1893 | + goto error; |
1894 | + |
1895 | + if (! state_get_json_int_var_to_obj (json, class, kill_signal)) |
1896 | + goto error; |
1897 | + |
1898 | + if (! state_get_json_int_var_to_obj (json, class, respawn)) |
1899 | + goto error; |
1900 | + |
1901 | + if (! state_get_json_int_var_to_obj (json, class, respawn_limit)) |
1902 | + goto error; |
1903 | + |
1904 | + if (! state_get_json_int_var_to_obj (json, class, respawn_interval)) |
1905 | + goto error; |
1906 | |
1907 | if (! state_get_json_enum_var (json, |
1908 | job_class_console_type_str_to_enum, |
1909 | - "console", partial->console)) |
1910 | - goto error; |
1911 | - |
1912 | - if (! state_get_json_int_var_to_obj (json, partial, umask)) |
1913 | - goto error; |
1914 | - |
1915 | - if (! state_get_json_int_var_to_obj (json, partial, nice)) |
1916 | - goto error; |
1917 | - |
1918 | - if (! state_get_json_int_var_to_obj (json, partial, oom_score_adj)) |
1919 | - goto error; |
1920 | - |
1921 | - if (! state_get_json_string_var_to_obj (json, partial, chroot)) |
1922 | - goto error; |
1923 | - |
1924 | - if (! state_get_json_string_var_to_obj (json, partial, chdir)) |
1925 | - goto error; |
1926 | - |
1927 | - if (! state_get_json_string_var_to_obj (json, partial, setuid)) |
1928 | - goto error; |
1929 | - |
1930 | - if (! state_get_json_string_var_to_obj (json, partial, setgid)) |
1931 | - goto error; |
1932 | - |
1933 | - if (! state_get_json_int_var_to_obj (json, partial, deleted)) |
1934 | - goto error; |
1935 | - |
1936 | - if (! state_get_json_int_var_to_obj (json, partial, debug)) |
1937 | - goto error; |
1938 | - |
1939 | - if (! state_get_json_string_var_to_obj (json, partial, usage)) |
1940 | - goto error; |
1941 | - |
1942 | - return partial; |
1943 | + "console", class->console)) |
1944 | + goto error; |
1945 | + |
1946 | + if (! state_get_json_int_var_to_obj (json, class, umask)) |
1947 | + goto error; |
1948 | + |
1949 | + if (! state_get_json_int_var_to_obj (json, class, nice)) |
1950 | + goto error; |
1951 | + |
1952 | + if (! state_get_json_int_var_to_obj (json, class, oom_score_adj)) |
1953 | + goto error; |
1954 | + |
1955 | + if (! state_get_json_string_var_to_obj (json, class, chroot)) |
1956 | + goto error; |
1957 | + |
1958 | + if (! state_get_json_string_var_to_obj (json, class, chdir)) |
1959 | + goto error; |
1960 | + |
1961 | + if (! state_get_json_string_var_to_obj (json, class, setuid)) |
1962 | + goto error; |
1963 | + |
1964 | + if (! state_get_json_string_var_to_obj (json, class, setgid)) |
1965 | + goto error; |
1966 | + |
1967 | + if (! state_get_json_int_var_to_obj (json, class, deleted)) |
1968 | + goto error; |
1969 | + |
1970 | + if (! state_get_json_int_var_to_obj (json, class, debug)) |
1971 | + goto error; |
1972 | + |
1973 | + if (! state_get_json_string_var_to_obj (json, class, usage)) |
1974 | + goto error; |
1975 | + |
1976 | + json_normalexit = json_object_object_get (json, "normalexit"); |
1977 | + if (! json_normalexit) |
1978 | + goto error; |
1979 | + |
1980 | + ret = state_deserialise_int_array (class, json_normalexit, |
1981 | + int, &class->normalexit, &class->normalexit_len); |
1982 | + if (ret < 0) |
1983 | + goto error; |
1984 | + |
1985 | + if (state_rlimit_deserialise_all (json, class, &class->limits) < 0) |
1986 | + goto error; |
1987 | + |
1988 | + if (process_deserialise_all (json, class->process, class->process) < 0) |
1989 | + goto error; |
1990 | + |
1991 | + /* Force class to be known. |
1992 | + * |
1993 | + * We cannot use job_class_*consider() since the |
1994 | + * JobClasses have no associated ConfFile. |
1995 | + */ |
1996 | + job_class_add_safe (class); |
1997 | + |
1998 | + /* Any jobs must be added after the class is registered |
1999 | + * (since you cannot add a job to a partially-created |
2000 | + * class). |
2001 | + */ |
2002 | + if (job_deserialise_all (class, json) < 0) |
2003 | + goto error; |
2004 | + |
2005 | + return class; |
2006 | |
2007 | error: |
2008 | - nih_free (partial); |
2009 | + nih_free (class); |
2010 | return NULL; |
2011 | } |
2012 | |
2013 | @@ -2015,9 +2035,7 @@ |
2014 | int |
2015 | job_class_deserialise_all (json_object *json) |
2016 | { |
2017 | - json_object *json_normalexit; |
2018 | JobClass *class = NULL; |
2019 | - int ret; |
2020 | |
2021 | nih_assert (json); |
2022 | |
2023 | @@ -2033,7 +2051,6 @@ |
2024 | |
2025 | for (int i = 0; i < json_object_array_length (json_classes); i++) { |
2026 | json_object *json_class; |
2027 | - nih_local JobClass *partial = NULL; |
2028 | |
2029 | json_class = json_object_array_get_idx (json_classes, i); |
2030 | if (! json_class) |
2031 | @@ -2042,13 +2059,10 @@ |
2032 | if (! state_check_json_type (json_class, object)) |
2033 | goto error; |
2034 | |
2035 | - partial = job_class_deserialise (json_class); |
2036 | - if (! partial) |
2037 | + class = job_class_deserialise (json_class); |
2038 | + if (! class) |
2039 | goto error; |
2040 | |
2041 | - class = NIH_MUST (job_class_new (NULL, partial->name, partial->session)); |
2042 | - |
2043 | -#if 1 |
2044 | /* FIXME: |
2045 | * |
2046 | * If user sessions exist (ie 'initctl --session list' |
2047 | @@ -2058,107 +2072,7 @@ |
2048 | * path set by job_class_new()='/com/ubuntu/Upstart/jobs/_/1000/bang' |
2049 | * |
2050 | */ |
2051 | -#endif |
2052 | - |
2053 | - /* job_class_new() sets path */ |
2054 | - nih_assert (! strcmp (class->path, partial->path)); |
2055 | - |
2056 | - if (! state_partial_copy_string (class, partial, description)) |
2057 | - goto error; |
2058 | - |
2059 | - if (! state_partial_copy_string (class, partial, author)) |
2060 | - goto error; |
2061 | - |
2062 | - if (! state_partial_copy_string (class, partial, version)) |
2063 | - goto error; |
2064 | - |
2065 | - if (! state_partial_copy_string (class, partial, chroot)) |
2066 | - goto error; |
2067 | - |
2068 | - if (! state_partial_copy_string (class, partial, chdir)) |
2069 | - goto error; |
2070 | - |
2071 | - if (! state_partial_copy_string (class, partial, setuid)) |
2072 | - goto error; |
2073 | - |
2074 | - if (! state_partial_copy_string (class, partial, setgid)) |
2075 | - goto error; |
2076 | - |
2077 | - if (! state_partial_copy_string (class, partial, usage)) |
2078 | - goto error; |
2079 | - |
2080 | - state_partial_copy_int (class, partial, expect); |
2081 | - state_partial_copy_int (class, partial, task); |
2082 | - state_partial_copy_int (class, partial, kill_timeout); |
2083 | - state_partial_copy_int (class, partial, kill_signal); |
2084 | - state_partial_copy_int (class, partial, respawn); |
2085 | - state_partial_copy_int (class, partial, respawn_limit); |
2086 | - state_partial_copy_int (class, partial, respawn_interval); |
2087 | - |
2088 | - json_normalexit = json_object_object_get (json_class, "normalexit"); |
2089 | - if (! json_normalexit) |
2090 | - goto error; |
2091 | - |
2092 | - ret = state_deserialise_int_array (class, json_normalexit, |
2093 | - int, &class->normalexit, &class->normalexit_len); |
2094 | - if (ret < 0) |
2095 | - goto error; |
2096 | - |
2097 | - state_partial_copy_int (class, partial, console); |
2098 | - state_partial_copy_int (class, partial, umask); |
2099 | - state_partial_copy_int (class, partial, nice); |
2100 | - state_partial_copy_int (class, partial, oom_score_adj); |
2101 | - state_partial_copy_int (class, partial, deleted); |
2102 | - state_partial_copy_int (class, partial, debug); |
2103 | - |
2104 | - if (state_rlimit_deserialise_all (json_class, class, &class->limits) < 0) |
2105 | - goto error; |
2106 | - |
2107 | - if (! state_copy_str_array_to_obj (class, partial, env)) |
2108 | - goto error; |
2109 | - |
2110 | - if (! state_copy_str_array_to_obj (class, partial, export)) |
2111 | - goto error; |
2112 | - |
2113 | - if (! state_copy_str_array_to_obj (class, partial, emits)) |
2114 | - goto error; |
2115 | - |
2116 | - if (! state_copy_event_oper_to_obj (class, partial, start_on)) |
2117 | - goto error; |
2118 | - |
2119 | - if (! state_copy_event_oper_to_obj (class, partial, stop_on)) |
2120 | - goto error; |
2121 | - |
2122 | - if (process_deserialise_all (json_class, class->process, class->process) < 0) |
2123 | - goto error; |
2124 | - |
2125 | - /* instance must have a value, but only set it if the |
2126 | - * partial value differs from the default set by |
2127 | - * job_class_new(). |
2128 | - */ |
2129 | - if (partial->instance && *partial->instance) { |
2130 | - nih_free (class->instance); |
2131 | - |
2132 | - class->instance = NIH_MUST (nih_strdup (class, partial->instance)); |
2133 | - } |
2134 | - |
2135 | - /* Force class to be known. |
2136 | - * |
2137 | - * We cannot use job_class_*consider() since the |
2138 | - * JobClasses have no associated ConfFile. |
2139 | - */ |
2140 | - job_class_add_safe (class); |
2141 | - |
2142 | - /* Any jobs must be added after the class is registered |
2143 | - * (since you cannot add a job to a partially-created |
2144 | - * class). |
2145 | - * |
2146 | - * Associated jobs are handled here rather than in |
2147 | - * job_class_deserialise() to avoid yet more data copying |
2148 | - * from 'partial' to 'class'. |
2149 | - */ |
2150 | - if (job_deserialise_all (class, json_class) < 0) |
2151 | - goto error; |
2152 | + |
2153 | } |
2154 | |
2155 | return 0; |
2156 | @@ -2250,3 +2164,59 @@ |
2157 | |
2158 | return -1; |
2159 | } |
2160 | + |
2161 | +/** |
2162 | + * job_class_prepare_reexec: |
2163 | + * |
2164 | + * Prepare for a re-exec by clearing the CLOEXEC bit on all log object |
2165 | + * file descriptors associated with their parent jobs. |
2166 | + **/ |
2167 | +void |
2168 | +job_class_prepare_reexec (void) |
2169 | +{ |
2170 | + job_class_init (); |
2171 | + |
2172 | + NIH_HASH_FOREACH (job_classes, iter) { |
2173 | + JobClass *class = (JobClass *)iter; |
2174 | + |
2175 | + NIH_HASH_FOREACH (class->instances, job_iter) { |
2176 | + Job *job = (Job *)job_iter; |
2177 | + |
2178 | + nih_assert (job->log); |
2179 | + |
2180 | + for (int process = 0; process < PROCESS_LAST; process++) { |
2181 | + int fd; |
2182 | + Log *log; |
2183 | + |
2184 | + log = job->log[process]; |
2185 | + |
2186 | + /* No associated job process or logger has detected |
2187 | + * remote end of pty has closed. |
2188 | + */ |
2189 | + if (! log || ! log->io) |
2190 | + continue; |
2191 | + |
2192 | + nih_assert (log->io->watch); |
2193 | + |
2194 | + fd = log->io->watch->fd; |
2195 | + if (fd < 0) |
2196 | + continue; |
2197 | + |
2198 | + if (state_toggle_cloexec (fd, FALSE) < 0) |
2199 | + goto error; |
2200 | + |
2201 | + fd = log->fd; |
2202 | + if (fd < 0) |
2203 | + continue; |
2204 | + |
2205 | + if (state_toggle_cloexec (fd, FALSE) < 0) |
2206 | + goto error; |
2207 | + } |
2208 | + } |
2209 | + } |
2210 | + |
2211 | + return; |
2212 | + |
2213 | +error: |
2214 | + nih_warn (_("unable to clear CLOEXEC bit on log fd")); |
2215 | +} |
2216 | |
2217 | === modified file 'init/job_class.h' |
2218 | --- init/job_class.h 2012-08-29 18:44:25 +0000 |
2219 | +++ init/job_class.h 2012-09-11 00:41:22 +0000 |
2220 | @@ -318,6 +318,8 @@ |
2221 | JobClass * job_class_get (const char *name, Session *session) |
2222 | __attribute__ ((warn_unused_result)); |
2223 | |
2224 | +void job_class_prepare_reexec (void); |
2225 | + |
2226 | NIH_END_EXTERN |
2227 | |
2228 | #endif /* INIT_JOB_CLASS_H */ |
2229 | |
2230 | === modified file 'init/log.c' |
2231 | --- init/log.c 2012-08-23 17:01:48 +0000 |
2232 | +++ init/log.c 2012-09-11 00:41:22 +0000 |
2233 | @@ -638,6 +638,8 @@ |
2234 | if (nih_io_buffer_resize (io->recv_buf, LOG_READ_SIZE) < 0) |
2235 | break; |
2236 | |
2237 | + errno = 0; |
2238 | + |
2239 | /* Append to buffer */ |
2240 | len = read (io->watch->fd, |
2241 | io->recv_buf->buf + io->recv_buf->len, |
2242 | @@ -680,22 +682,23 @@ |
2243 | * causes the loop to be exited. |
2244 | */ |
2245 | if (len <= 0) { |
2246 | + /* Job process has ended and we've drained all the data the job |
2247 | + * produced, so remote end must have closed. |
2248 | + * |
2249 | + * This cannot be handled entirely by log_io_error_handler() |
2250 | + * since the job may produce some output prior to disks being |
2251 | + * writeable, then end without producing further output. |
2252 | + * In this scenario the error handler is never called. |
2253 | + * |
2254 | + */ |
2255 | + if (saved && saved != EAGAIN && saved != EWOULDBLOCK) |
2256 | + log->remote_closed = 1; |
2257 | + |
2258 | close (log->fd); |
2259 | log->fd = -1; |
2260 | break; |
2261 | } |
2262 | } |
2263 | - |
2264 | - /* Job process has ended and we've drained all the data the job |
2265 | - * produced, so remote end must have closed. |
2266 | - * |
2267 | - * This cannot be handled entirely by log_io_error_handler() |
2268 | - * since the job may produce some output prior to disks being |
2269 | - * writeable, then end without producing further output. |
2270 | - * In this scenario the error handler is never called. |
2271 | - * |
2272 | - */ |
2273 | - log->remote_closed = 1; |
2274 | } |
2275 | |
2276 | /** |
2277 | @@ -821,20 +824,35 @@ |
2278 | * Returns: JSON-serialised Log object, or NULL on error. |
2279 | **/ |
2280 | json_object * |
2281 | -log_serialise (const Log *log) |
2282 | +log_serialise (Log *log) |
2283 | { |
2284 | - json_object *json; |
2285 | + json_object *json; |
2286 | + nih_local char *unflushed_hex = NULL; |
2287 | |
2288 | json = json_object_new_object (); |
2289 | if (! json) |
2290 | return NULL; |
2291 | |
2292 | - if (! log) |
2293 | + if (! log || ! log->io || log->remote_closed) { |
2294 | + /* Create a "placeholder" log object for non-existent |
2295 | + * log objects and for those that are no longer usable. |
2296 | + */ |
2297 | + if (! state_set_json_string_var (json, "path", "")) |
2298 | + goto error; |
2299 | return json; |
2300 | + } |
2301 | + |
2302 | + /* Attempt to flush any cached data */ |
2303 | + log_flush (log); |
2304 | |
2305 | if (! state_set_json_int_var_from_obj (json, log, fd)) |
2306 | goto error; |
2307 | |
2308 | + nih_assert (log->io->watch); |
2309 | + |
2310 | + if (! state_set_json_int_var (json, "io_watch_fd", log->io->watch->fd)) |
2311 | + goto error; |
2312 | + |
2313 | if (! state_set_json_string_var_from_obj (json, log, path)) |
2314 | goto error; |
2315 | |
2316 | @@ -843,9 +861,19 @@ |
2317 | if (! state_set_json_int_var_from_obj (json, log, uid)) |
2318 | goto error; |
2319 | |
2320 | + /* Encode unflushed data as hex to ensure any embedded |
2321 | + * nulls are handled. |
2322 | + */ |
2323 | if (log->unflushed->len) { |
2324 | - if (! state_set_json_string_var (json, "unflushed", log->unflushed->buf)) |
2325 | - goto error; |
2326 | + unflushed_hex = state_data_to_hex (NULL, |
2327 | + log->unflushed->buf, |
2328 | + log->unflushed->len); |
2329 | + |
2330 | + if (! unflushed_hex) |
2331 | + goto error; |
2332 | + |
2333 | + if (! state_set_json_string_var (json, "unflushed", unflushed_hex)) |
2334 | + goto error; |
2335 | } |
2336 | |
2337 | if (! state_set_json_int_var_from_obj (json, log, detached)) |
2338 | @@ -868,18 +896,23 @@ |
2339 | * log_deserialise: |
2340 | * @json: JSON-serialised Log object to deserialise. |
2341 | * |
2342 | - * Convert @json into a partial Log object. |
2343 | - * |
2344 | - * Note that the object returned is not a true Log since not all |
2345 | - * structure elements are encoded in the JSON. |
2346 | - * |
2347 | - * Returns: partial Log object, or NULL on error. |
2348 | + * Convert @json into a Log object. |
2349 | + * |
2350 | + * Returns: Log object, or NULL on error. |
2351 | **/ |
2352 | Log * |
2353 | -log_deserialise (json_object *json) |
2354 | +log_deserialise (const void *parent, |
2355 | + json_object *json) |
2356 | { |
2357 | - Log *partial; |
2358 | + Log *log; |
2359 | + nih_local char *unflushed_hex = NULL; |
2360 | nih_local char *unflushed = NULL; |
2361 | + int ret; |
2362 | + size_t len; |
2363 | + json_object *json_unflushed; |
2364 | + nih_local char *path = NULL; |
2365 | + int fd; |
2366 | + uid_t uid; |
2367 | |
2368 | nih_assert (json); |
2369 | |
2370 | @@ -888,43 +921,71 @@ |
2371 | if (! state_check_json_type (json, object)) |
2372 | return NULL; |
2373 | |
2374 | - partial = nih_new (NULL, Log); |
2375 | - if (! partial) |
2376 | - return NULL; |
2377 | - |
2378 | - memset (partial, '\0', sizeof (Log)); |
2379 | - |
2380 | - if (! state_get_json_int_var_to_obj (json, partial, fd)) |
2381 | - goto error; |
2382 | - |
2383 | - if (! state_get_json_string_var_to_obj (json, partial, path)) |
2384 | - goto error; |
2385 | - |
2386 | - if (! state_get_json_int_var_to_obj (json, partial, uid)) |
2387 | - goto error; |
2388 | - |
2389 | - partial->unflushed = nih_io_buffer_new (partial); |
2390 | - if (! partial->unflushed) |
2391 | - goto error; |
2392 | - |
2393 | - if (! state_get_json_string_var (json, "unflushed", NULL, unflushed)) |
2394 | - goto error; |
2395 | - |
2396 | - if (nih_io_buffer_push (partial->unflushed, unflushed, strlen (unflushed)) < 0) |
2397 | - goto error; |
2398 | - |
2399 | - if (! state_get_json_int_var_to_obj (json, partial, detached)) |
2400 | - goto error; |
2401 | - |
2402 | - if (! state_get_json_int_var_to_obj (json, partial, remote_closed)) |
2403 | - goto error; |
2404 | - |
2405 | - if (! state_get_json_int_var_to_obj (json, partial, open_errno)) |
2406 | - goto error; |
2407 | - |
2408 | - return partial; |
2409 | + if (! state_get_json_string_var (json, "path", NULL, path)) |
2410 | + return NULL; |
2411 | + |
2412 | + if (! *path) { |
2413 | + /* placeholder log object */ |
2414 | + return NULL; |
2415 | + } |
2416 | + |
2417 | + if (! state_get_json_int_var (json, "io_watch_fd", fd)) |
2418 | + return NULL; |
2419 | + |
2420 | + /* re-apply CLOEXEC flag to stop fd being leaked to children */ |
2421 | + if (fd != -1 && state_toggle_cloexec (fd, TRUE) < 0) |
2422 | + return NULL; |
2423 | + |
2424 | + if (! state_get_json_int_var (json, "uid", uid)) |
2425 | + return NULL; |
2426 | + |
2427 | + log = log_new (parent, path, fd, uid); |
2428 | + if (! log) |
2429 | + return NULL; |
2430 | + |
2431 | + if (! state_get_json_int_var_to_obj (json, log, fd)) |
2432 | + goto error; |
2433 | + |
2434 | + /* Stop fd leaking to children */ |
2435 | + if (log->fd != -1) { |
2436 | + if (state_toggle_cloexec (log->fd, TRUE) < 0) |
2437 | + goto error; |
2438 | + } |
2439 | + |
2440 | + log->unflushed = nih_io_buffer_new (log); |
2441 | + if (! log->unflushed) |
2442 | + goto error; |
2443 | + |
2444 | + json_unflushed = json_object_object_get (json, "unflushed"); |
2445 | + if (json_unflushed) { |
2446 | + if (! state_get_json_string_var (json, "unflushed", NULL, unflushed_hex)) |
2447 | + goto error; |
2448 | + |
2449 | + ret = state_hex_to_data (NULL, |
2450 | + unflushed_hex, |
2451 | + strlen (unflushed_hex), |
2452 | + &unflushed, |
2453 | + &len); |
2454 | + |
2455 | + if (ret < 0) |
2456 | + goto error; |
2457 | + |
2458 | + if (nih_io_buffer_push (log->unflushed, unflushed, len) < 0) |
2459 | + goto error; |
2460 | + } |
2461 | + |
2462 | + if (! state_get_json_int_var_to_obj (json, log, detached)) |
2463 | + goto error; |
2464 | + |
2465 | + if (! state_get_json_int_var_to_obj (json, log, remote_closed)) |
2466 | + goto error; |
2467 | + |
2468 | + if (! state_get_json_int_var_to_obj (json, log, open_errno)) |
2469 | + goto error; |
2470 | + |
2471 | + return log; |
2472 | |
2473 | error: |
2474 | - nih_free (partial); |
2475 | + nih_free (log); |
2476 | return NULL; |
2477 | } |
2478 | |
2479 | === modified file 'init/log.h' |
2480 | --- init/log.h 2012-08-23 17:01:48 +0000 |
2481 | +++ init/log.h 2012-09-11 00:41:22 +0000 |
2482 | @@ -88,9 +88,9 @@ |
2483 | int log_clear_unflushed (void) |
2484 | __attribute__ ((warn_unused_result)); |
2485 | void log_unflushed_init (void); |
2486 | -json_object * log_serialise (const Log *log) |
2487 | +json_object * log_serialise (Log *log) |
2488 | __attribute__ ((warn_unused_result, malloc)); |
2489 | -Log * log_deserialise (json_object *json) |
2490 | +Log * log_deserialise (const void *parent, json_object *json) |
2491 | __attribute__ ((warn_unused_result, malloc)); |
2492 | |
2493 | NIH_END_EXTERN |
2494 | |
2495 | === modified file 'init/main.c' |
2496 | --- init/main.c 2012-08-24 15:52:22 +0000 |
2497 | +++ init/main.c 2012-09-11 00:41:22 +0000 |
2498 | @@ -491,7 +491,7 @@ |
2499 | NIH_MUST (conf_source_new (NULL, CONFFILE, CONF_FILE)); |
2500 | NIH_MUST (conf_source_new (NULL, conf_dir, CONF_JOB_DIR)); |
2501 | |
2502 | - conf_reload (restart); |
2503 | + conf_reload (); |
2504 | |
2505 | /* Create a listening server for private connections. */ |
2506 | if (use_session_bus == FALSE) { |
2507 | @@ -513,7 +513,7 @@ |
2508 | * fail (since dbus-daemon probably isn't running yet) and will try again |
2509 | * later - don't let ENOMEM stop us though. |
2510 | */ |
2511 | - while (control_bus_open (restart) < 0) { |
2512 | + while (control_bus_open () < 0) { |
2513 | NihError *err; |
2514 | int number; |
2515 | |
2516 | @@ -831,7 +831,7 @@ |
2517 | NihSignal *signal) |
2518 | { |
2519 | nih_info (_("Reloading configuration")); |
2520 | - conf_reload (restart); |
2521 | + conf_reload (); |
2522 | } |
2523 | |
2524 | /** |
2525 | @@ -849,7 +849,7 @@ |
2526 | if (! control_bus) { |
2527 | nih_info (_("Reconnecting to system bus")); |
2528 | |
2529 | - if (control_bus_open (restart) < 0) { |
2530 | + if (control_bus_open () < 0) { |
2531 | NihError *err; |
2532 | |
2533 | err = nih_error_get (); |
2534 | @@ -1033,6 +1033,9 @@ |
2535 | /* retain the D-Bus connection across the re-exec */ |
2536 | control_prepare_reexec (); |
2537 | |
2538 | + /* Clear CLOEXEC flag for any job log objects prior to re-exec */ |
2539 | + job_class_prepare_reexec (); |
2540 | + |
2541 | pid = fork (); |
2542 | |
2543 | if (pid < 0) |
2544 | |
2545 | === modified file 'init/parse_job.c' |
2546 | --- init/parse_job.c 2012-08-23 17:01:48 +0000 |
2547 | +++ init/parse_job.c 2012-09-11 00:41:22 +0000 |
2548 | @@ -520,7 +520,7 @@ |
2549 | * Returns: EventOperator at root of expression tree on success, NULL |
2550 | * on raised error. |
2551 | **/ |
2552 | -EventOperator * |
2553 | +static EventOperator * |
2554 | parse_on (JobClass *class, |
2555 | NihConfigStanza *stanza, |
2556 | const char *file, |
2557 | |
2558 | === modified file 'init/paths.h' |
2559 | --- init/paths.h 2012-06-19 16:40:35 +0000 |
2560 | +++ init/paths.h 2012-09-11 00:41:22 +0000 |
2561 | @@ -127,34 +127,6 @@ |
2562 | #endif |
2563 | |
2564 | /** |
2565 | - * UPSTART: |
2566 | - * |
2567 | - * The upstart binary. |
2568 | - **/ |
2569 | -#ifndef UPSTART |
2570 | - |
2571 | -/* * * * * * * * * * *** * * * * * * * * * ** * * * * * ** * * * * */ |
2572 | -/* * * * ** * **** * ** ** * * * * * ** * * ** * * * * * * * * * */ |
2573 | -/* FIXME */ |
2574 | -/* FIXME */ |
2575 | -/* FIXME: |
2576 | - * |
2577 | - */ |
2578 | - |
2579 | -#if 0 |
2580 | -#define UPSTART SBINDIR "/init" |
2581 | -#endif |
2582 | -#define UPSTART "/data/bzr/upstart/upstart/init/init" |
2583 | - |
2584 | -/* FIXME */ |
2585 | -/* FIXME */ |
2586 | -/* * * * ** * **** * ** ** * * * * * ** * * ** * * * * * * * * * */ |
2587 | -/* * * * * * * * * * *** * * * * * * * * * ** * * * * * ** * * * * */ |
2588 | -/* * * * ** * **** * ** ** * * * * * ** * * ** * * * * * * * * * */ |
2589 | - |
2590 | -#endif |
2591 | - |
2592 | -/** |
2593 | * JOB_LOGDIR: |
2594 | * |
2595 | * Directory that jobs which specify CONSOLE_LOG will have their output |
2596 | |
2597 | === modified file 'init/process.c' |
2598 | --- init/process.c 2012-08-28 16:29:50 +0000 |
2599 | +++ init/process.c 2012-09-11 00:41:22 +0000 |
2600 | @@ -209,17 +209,9 @@ |
2601 | * |
2602 | * Convert @json into a Process object. |
2603 | * |
2604 | - * Caller must manually nih_ref() returned object to a parent object. |
2605 | - * |
2606 | * Returns: Process object, or NULL on error. |
2607 | **/ |
2608 | |
2609 | -#if 1 |
2610 | -/* FIXME: should we just make this the same as the other partial |
2611 | - * objects for consistency? |
2612 | - */ |
2613 | -#endif |
2614 | - |
2615 | static Process * |
2616 | process_deserialise (json_object *json, const void *parent) |
2617 | { |
2618 | @@ -232,14 +224,22 @@ |
2619 | |
2620 | process = NIH_MUST (process_new (parent)); |
2621 | |
2622 | - memset (process, '\0', sizeof (Process)); |
2623 | - |
2624 | if (! state_get_json_int_var_to_obj (json, process, script)) |
2625 | goto error; |
2626 | |
2627 | if (! state_get_json_string_var_to_obj (json, process, command)) |
2628 | goto error; |
2629 | |
2630 | + /* All Process slots have to be serialised in the JSON to |
2631 | + * guarantee ordering on deserialisation. |
2632 | + * |
2633 | + * However, here we've found a Process that was merely |
2634 | + * an ordering placeholder - no command has been defined, |
2635 | + * so ignore it. |
2636 | + */ |
2637 | + if (! process->command || ! *process->command) |
2638 | + goto error; |
2639 | + |
2640 | return process; |
2641 | |
2642 | error: |
2643 | @@ -265,7 +265,6 @@ |
2644 | { |
2645 | json_object *json_processes; |
2646 | Process *process; |
2647 | - nih_local Process *partial = NULL; |
2648 | int i; |
2649 | |
2650 | nih_assert (json); |
2651 | @@ -292,27 +291,8 @@ |
2652 | if (! state_check_json_type (json_process, object)) |
2653 | goto error; |
2654 | |
2655 | - partial = process_deserialise (json_process, partial); |
2656 | - if (! partial) |
2657 | - goto error; |
2658 | - |
2659 | - /* All Process slots have to be serialised in the JSON to |
2660 | - * guarantee ordering on deserialisation. |
2661 | - * |
2662 | - * However, here we've found a Process that was merely |
2663 | - * an ordering placeholder - no command has been defined, |
2664 | - * so ignore it. |
2665 | - */ |
2666 | - if (! partial->command || ! *partial->command) { |
2667 | - processes[i] = NULL; |
2668 | - continue; |
2669 | - } |
2670 | - |
2671 | - process = NIH_MUST (process_new (parent)); |
2672 | - process->command = NIH_MUST (nih_strdup (processes, partial->command)); |
2673 | - process->script = partial->script; |
2674 | - |
2675 | - processes[i] = process; |
2676 | + processes[i] = process_deserialise (json_process, parent); |
2677 | + |
2678 | } |
2679 | |
2680 | return 0; |
2681 | |
2682 | === modified file 'init/session.c' |
2683 | --- init/session.c 2012-08-14 16:13:48 +0000 |
2684 | +++ init/session.c 2012-09-11 00:41:22 +0000 |
2685 | @@ -476,42 +476,47 @@ |
2686 | * session_deserialise: |
2687 | * @json: JSON-serialised Session object to deserialise. |
2688 | * |
2689 | - * Convert @json into a partial Session object. |
2690 | - * |
2691 | - * Note that the object returned is not a true Session since not all |
2692 | - * structure elements are encoded in the JSON. |
2693 | - * |
2694 | - * Returns: partial Session object, or NULL on error. |
2695 | + * Convert @json into a Session object. |
2696 | + * |
2697 | + * Returns: Session object, or NULL on error. |
2698 | **/ |
2699 | static Session * |
2700 | session_deserialise (json_object *json) |
2701 | { |
2702 | - Session *partial; |
2703 | + Session *session; |
2704 | + nih_local const char *chroot; |
2705 | + uid_t user; |
2706 | |
2707 | nih_assert (json); |
2708 | |
2709 | if (! state_check_json_type (json, object)) |
2710 | return NULL; |
2711 | |
2712 | - partial = nih_new (NULL, Session); |
2713 | - if (! partial) |
2714 | - return NULL; |
2715 | - |
2716 | - memset (partial, '\0', sizeof (Session)); |
2717 | - |
2718 | - if (! state_get_json_string_var_to_obj (json, partial, chroot)) |
2719 | - goto error; |
2720 | - |
2721 | - if (! state_get_json_int_var_to_obj (json, partial, user)) |
2722 | - goto error; |
2723 | - |
2724 | - if (! state_get_json_string_var_to_obj (json, partial, conf_path)) |
2725 | - goto error; |
2726 | - |
2727 | - return partial; |
2728 | + if (! state_get_json_string_var (json, "chroot", NULL, chroot)) |
2729 | + return NULL; |
2730 | + |
2731 | + if (! state_get_json_int_var (json, "user", user)) |
2732 | + return NULL; |
2733 | + |
2734 | + /* Create a new session */ |
2735 | + session = NIH_MUST (session_new (NULL, chroot, user)); |
2736 | + |
2737 | + if (! state_get_json_string_var_to_obj (json, session, conf_path)) |
2738 | + goto error; |
2739 | + |
2740 | + /* Not an error, just the representation of the "NULL session" */ |
2741 | + if (! *session->chroot && ! session->user && ! *session->conf_path) |
2742 | + goto error; |
2743 | + |
2744 | + if (! *session->chroot) |
2745 | + { |
2746 | + nih_free (session->chroot); |
2747 | + session->chroot = NULL; |
2748 | + } |
2749 | + return session; |
2750 | |
2751 | error: |
2752 | - nih_free (partial); |
2753 | + nih_free (session); |
2754 | return NULL; |
2755 | } |
2756 | |
2757 | @@ -528,19 +533,12 @@ |
2758 | session_deserialise_all (json_object *json) |
2759 | { |
2760 | Session *session; |
2761 | - nih_local Session *partial = NULL; |
2762 | |
2763 | nih_assert (json); |
2764 | |
2765 | session_init (); |
2766 | |
2767 | - /* FIXME: enable for final build */ |
2768 | -#if PRODUCTION_BUILD |
2769 | nih_assert (NIH_LIST_EMPTY (sessions)); |
2770 | -#else |
2771 | - nih_warn ("XXX: WARNING (%s:%d): NIH_LIST_EMPTY(sessions) check disabled", |
2772 | - __func__, __LINE__); |
2773 | -#endif |
2774 | |
2775 | json_sessions = json_object_object_get (json, "sessions"); |
2776 | |
2777 | @@ -560,20 +558,14 @@ |
2778 | if (! state_check_json_type (json_session, object)) |
2779 | goto error; |
2780 | |
2781 | - partial = session_deserialise (json_session); |
2782 | - if (! partial) |
2783 | - goto error; |
2784 | - |
2785 | - if (! *partial->chroot && ! partial->user && ! *partial->conf_path) { |
2786 | - /* Ignore the "NULL session" which is represented |
2787 | - * by NULL, not an "empty session" internally. |
2788 | - */ |
2789 | + session = session_deserialise (json_session); |
2790 | + /* Ignore the "NULL session" which is represented |
2791 | + * by NULL, not an "empty session" internally. |
2792 | + */ |
2793 | + if (! session) |
2794 | continue; |
2795 | - } |
2796 | |
2797 | - /* Create a new session and associated ConfSource */ |
2798 | - session = NIH_MUST (session_new (NULL, partial->chroot, partial->user)); |
2799 | - session->conf_path = NIH_MUST (nih_strdup (session, partial->conf_path)); |
2800 | + /* Create the associated ConfSource */ |
2801 | session_create_conf_source (session, TRUE); |
2802 | } |
2803 | |
2804 | |
2805 | === modified file 'init/state.c' |
2806 | --- init/state.c 2012-08-24 16:15:52 +0000 |
2807 | +++ init/state.c 2012-09-11 00:41:22 +0000 |
2808 | @@ -46,7 +46,6 @@ |
2809 | json_object *json_sessions = NULL; |
2810 | json_object *json_events = NULL; |
2811 | json_object *json_classes = NULL; |
2812 | -json_object *json_control_conns = NULL; |
2813 | |
2814 | extern int use_session_bus; |
2815 | |
2816 | @@ -73,16 +72,6 @@ |
2817 | state_get_job (const char *job_class, const char *job_name) |
2818 | __attribute__ ((warn_unused_result)); |
2819 | |
2820 | -static char * |
2821 | -state_data_to_hex (void *parent, const void *data, size_t len) |
2822 | - __attribute__ ((warn_unused_result)); |
2823 | - |
2824 | -static int |
2825 | -state_hex_to_data (void *parent, const void *hex_data, |
2826 | - size_t hex_len, char **data, |
2827 | - size_t *data_len) |
2828 | - __attribute__ ((warn_unused_result)); |
2829 | - |
2830 | /** |
2831 | * state_read: |
2832 | * |
2833 | @@ -369,12 +358,6 @@ |
2834 | |
2835 | json_object_object_add (json, "sessions", json_sessions); |
2836 | |
2837 | - json_control_conns = control_serialise_all (); |
2838 | - if (! json_control_conns) |
2839 | - goto error; |
2840 | - |
2841 | - json_object_object_add (json, "control_conns", json_control_conns); |
2842 | - |
2843 | json_events = event_serialise_all (); |
2844 | if (! json_events) |
2845 | goto error; |
2846 | @@ -480,9 +463,6 @@ |
2847 | if (job_class_deserialise_all (json) < 0) |
2848 | goto out; |
2849 | |
2850 | - if (control_deserialise_all (json) < 0) |
2851 | - goto out; |
2852 | - |
2853 | if (state_deserialise_resolve_deps (json) < 0) |
2854 | goto out; |
2855 | |
2856 | @@ -644,7 +624,6 @@ |
2857 | size_t len = 0; |
2858 | char **array = NULL; |
2859 | |
2860 | - nih_assert (parent); |
2861 | nih_assert (json); |
2862 | |
2863 | if (! state_check_json_type (json, array)) |
2864 | @@ -1200,7 +1179,6 @@ |
2865 | nih_assert (json_sessions); |
2866 | nih_assert (json_events); |
2867 | nih_assert (json_classes); |
2868 | - nih_assert (json_control_conns); |
2869 | |
2870 | for (int i = 0; i < json_object_array_length (json_events); i++) { |
2871 | json_object *json_event; |
2872 | @@ -1778,7 +1756,7 @@ |
2873 | * Returns: newly-allocated hex-encoded string, |
2874 | * or NULL on error. |
2875 | **/ |
2876 | -static char * |
2877 | +char * |
2878 | state_data_to_hex (void *parent, const void *data, size_t len) |
2879 | { |
2880 | unsigned char *p; |
2881 | @@ -1818,8 +1796,8 @@ |
2882 | * |
2883 | * Returns: 0 on success, -1 on error. |
2884 | **/ |
2885 | -static int |
2886 | -state_hex_to_data (void *parent, |
2887 | +int |
2888 | +state_hex_to_data (void *parent, |
2889 | const void *hex_data, |
2890 | size_t hex_len, |
2891 | char **data, |
2892 | |
2893 | === modified file 'init/state.h' |
2894 | --- init/state.h 2012-08-24 15:52:22 +0000 |
2895 | +++ init/state.h 2012-09-11 00:41:22 +0000 |
2896 | @@ -57,8 +57,6 @@ |
2897 | * XXX:XXX: * XXX:XXX: * XXX:XXX: * XXX:XXX: * XXX:XXX: * XXX:XXX: |
2898 | *-------------------------------------------------------------------- |
2899 | * |
2900 | - * - remove all PRODUCTION_BUILD macros and adopt production flow. |
2901 | - * |
2902 | * - check "NULL session" deserialisation handling. |
2903 | * |
2904 | * - XXX: audit memory management for all *_deserialise() and |
2905 | @@ -108,23 +106,6 @@ |
2906 | * into an array of Process objects which are then hooked onto a |
2907 | * JobClass object). |
2908 | * |
2909 | - * Note that objects returned by <object_>_deserialise() are generally |
2910 | - * _partial_ objects: they are not true objects since they have not |
2911 | - * been constructed. They are like templates for the real objects with |
2912 | - * those elements filled in that the JSON encodes. |
2913 | - * |
2914 | - * Each partial object needs to be converted into a real object by: |
2915 | - * |
2916 | - * - creating an instance of that object (using <object_>_new()). |
2917 | - * - copying the element data from the partial object back into the real |
2918 | - * object. |
2919 | - * |
2920 | - * These steps happens in <object_>_deserialise_all(). It is rather |
2921 | - * tedious but does ensure that the resultant object is "sane". It |
2922 | - * is also essential since the JSON representation of most objects does |
2923 | - * _NOT_ encode all information about an object (for example the JSON |
2924 | - * encoding for an Event does not encode 'blockers' and 'blocking'). |
2925 | - * |
2926 | * == Error Handling == |
2927 | * |
2928 | * If stateful re-exec fails, Upstart must perform a stateless reexec: |
2929 | @@ -1144,6 +1125,15 @@ |
2930 | int state_fd_valid (int fd) |
2931 | __attribute__ ((warn_unused_result)); |
2932 | |
2933 | +char * state_data_to_hex (void *parent, const void *data, |
2934 | + size_t len) |
2935 | + __attribute__ ((warn_unused_result)); |
2936 | + |
2937 | +int state_hex_to_data (void *parent, const void *hex_data, |
2938 | + size_t hex_len, char **data, |
2939 | + size_t *data_len) |
2940 | + __attribute__ ((warn_unused_result)); |
2941 | + |
2942 | NIH_END_EXTERN |
2943 | |
2944 | #endif /* INIT_STATE_H */ |
2945 | |
2946 | === modified file 'init/tests/test_conf.c' |
2947 | --- init/tests/test_conf.c 2012-08-24 19:55:22 +0000 |
2948 | +++ init/tests/test_conf.c 2012-09-11 00:41:22 +0000 |
2949 | @@ -4549,7 +4549,7 @@ |
2950 | strcat (filename, "/baz"); |
2951 | source3 = conf_source_new (NULL, filename, CONF_DIR); |
2952 | |
2953 | - conf_reload (FALSE); |
2954 | + conf_reload (); |
2955 | |
2956 | TEST_HASH_NOT_EMPTY (source1->files); |
2957 | |
2958 | |
2959 | === modified file 'init/tests/test_control.c' |
2960 | --- init/tests/test_control.c 2012-08-24 20:08:54 +0000 |
2961 | +++ init/tests/test_control.c 2012-09-11 00:41:22 +0000 |
2962 | @@ -486,7 +486,7 @@ |
2963 | setenv ("DBUS_SYSTEM_BUS_ADDRESS", |
2964 | "unix:abstract=/com/ubuntu/upstart/test", TRUE); |
2965 | |
2966 | - ret = control_bus_open (FALSE); |
2967 | + ret = control_bus_open (); |
2968 | |
2969 | TEST_EQ (ret, 0); |
2970 | TEST_NE_P (control_bus, NULL); |
2971 | @@ -571,7 +571,7 @@ |
2972 | setenv ("DBUS_SYSTEM_BUS_ADDRESS", |
2973 | "unix:abstract=/com/ubuntu/upstart/test", TRUE); |
2974 | |
2975 | - ret = control_bus_open (FALSE); |
2976 | + ret = control_bus_open (); |
2977 | |
2978 | TEST_EQ (ret, 0); |
2979 | TEST_NE_P (control_bus, NULL); |
2980 | @@ -675,7 +675,7 @@ |
2981 | setenv ("DBUS_SYSTEM_BUS_ADDRESS", |
2982 | "unix:abstract=/com/ubuntu/upstart/test", TRUE); |
2983 | |
2984 | - ret = control_bus_open (FALSE); |
2985 | + ret = control_bus_open (); |
2986 | |
2987 | TEST_LT (ret, 0); |
2988 | TEST_EQ_P (control_bus, NULL); |
2989 | @@ -739,7 +739,7 @@ |
2990 | setenv ("DBUS_SYSTEM_BUS_ADDRESS", |
2991 | "unix:abstract=/com/ubuntu/upstart/test", TRUE); |
2992 | |
2993 | - ret = control_bus_open (FALSE); |
2994 | + ret = control_bus_open (); |
2995 | |
2996 | TEST_LT (ret, 0); |
2997 | TEST_EQ_P (control_bus, NULL); |
2998 | @@ -767,7 +767,7 @@ |
2999 | setenv ("DBUS_SYSTEM_BUS_ADDRESS", |
3000 | "unix:abstract=/com/ubuntu/upstart/test", TRUE); |
3001 | |
3002 | - ret = control_bus_open (FALSE); |
3003 | + ret = control_bus_open (); |
3004 | |
3005 | TEST_LT (ret, 0); |
3006 | TEST_EQ_P (control_bus, NULL); |
3007 | @@ -802,7 +802,7 @@ |
3008 | |
3009 | assert (NIH_LIST_EMPTY (control_conns)); |
3010 | |
3011 | - assert0 (control_bus_open (FALSE)); |
3012 | + assert0 (control_bus_open ()); |
3013 | assert (control_bus != NULL); |
3014 | |
3015 | assert (! NIH_LIST_EMPTY (control_conns)); |
3016 | @@ -856,7 +856,7 @@ |
3017 | |
3018 | TEST_DBUS (dbus_pid); |
3019 | |
3020 | - assert0 (control_bus_open (FALSE)); |
3021 | + assert0 (control_bus_open ()); |
3022 | assert (control_bus != NULL); |
3023 | |
3024 | assert (! NIH_LIST_EMPTY (control_conns)); |
3025 | |
3026 | === modified file 'init/tests/test_event_operator.c' |
3027 | --- init/tests/test_event_operator.c 2012-08-31 14:42:40 +0000 |
3028 | +++ init/tests/test_event_operator.c 2012-09-11 00:41:22 +0000 |
3029 | @@ -1327,7 +1327,7 @@ |
3030 | { |
3031 | JobClass *job = NULL; |
3032 | EventOperator *oper1, *oper2; |
3033 | - char *oper1_string; |
3034 | + char *oper1_string; |
3035 | |
3036 | struct test_operator { |
3037 | char *description; |