Merge lp:~jamesodhunt/upstart/serialise-remaining-objects into lp:upstart
- serialise-remaining-objects
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 1479 |
Proposed branch: | lp:~jamesodhunt/upstart/serialise-remaining-objects |
Merge into: | lp:upstart |
Diff against target: |
58491 lines (+56824/-375) 26 files modified
ChangeLog (+274/-0) init/Makefile.am (+1/-1) init/conf.c (+651/-11) init/conf.h (+57/-1) init/control.h (+25/-25) init/event.c (+14/-4) init/event_operator.c (+311/-3) init/event_operator.h (+26/-1) init/job.c (+56/-46) init/job.h (+2/-2) init/job_class.c (+288/-131) init/job_class.h (+9/-3) init/main.c (+4/-0) init/paths.h (+9/-0) init/state.c (+87/-30) init/state.h (+5/-8) init/tests/data/upstart-1.8+apparmor.json (+7962/-0) init/tests/data/upstart-1.8+full_serialisation+apparmor.json (+18886/-0) init/tests/data/upstart-1.8+full_serialisation-apparmor.json (+18201/-0) init/tests/data/upstart-1.8.json (+8651/-0) init/tests/test_conf.c (+306/-3) init/tests/test_event_operator.c (+25/-5) init/tests/test_job.c (+31/-10) init/tests/test_state.c (+845/-90) init/tests/test_util.c (+85/-0) init/tests/test_util.h (+13/-1) |
To merge this branch: | bzr merge lp:~jamesodhunt/upstart/serialise-remaining-objects |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Hunt | Needs Resubmitting | ||
Steve Langasek | Needs Fixing | ||
Review via email: mp+163151@code.launchpad.net |
Commit message
Description of the change
This monster MP includes fixes for two bugs:
= bug 1124384 =
This bug has seemingly existed for a long time and only came to light when users of cloud-init attempted to overcome the inotify limitations of overlayfs (see bug 882147) by invoking 'initctl reload-
The issue has nothing to do with early boot though - potentially, whenever 'initctl reload-
The fix involved deferring the destruction of the original ConfFile object coupled with code to allow the newly-created (post-reload) JobClass to reference any relevant events before the original ConfFile and JobClass are destroyed. This allows the event reference count to stay positive across a reload.
= bug 1103881 =
This is an issue with stateful re-exec: the original approach was to serialise the start/stop on conditions as a logically identical representation of the original string from the .conf file. However, this meant that required EventOperator data was not available on deserialisation. This resulted in the possibility that events would be destroyed too early since their reference counts could drop to zero as the EventOperator references to those evens would not be re-instated post-re-exec.
The new approach is to:
1) Serialise the start/stop on conditions as full EventOperator trees.
2) Serialise all objects, regardless of whether they are currently being referenced by running jobs.
New objects being serialised are:
- ConfSource
- ConfFile
- EventOperator
Since all objects are now being serialised, chroot sessions can now be supported. These changes would also support upstart-
- 1481. By James Hunt
-
* Merge of lp:upstart.
- 1482. By James Hunt
-
Revert to not supporting deserialisation of JobClasses with associated
user/chroot sessions to avoid behavioural change for now.* init/job_class.c:
- job_class_deserialise( ): Revert to failing if associated session is
non-NULL.
- job_class_deserialise_ all(): Revert to ignoring failure to
deserialise a JobClass iff it has a non-NULL associated session.
* init/state.c:
- state_to_string(): Provide some diagnostics if serialisation fails.
- state_from_string( ): Provide some diagnostics if deserialisation fails.
- state_deserialise_resolve_ deps(): Ignore failure to lookup JobClass
iff it has an associated user/chroot session.
- state_deserialise_blocking( ): Revert to ignoring failure to
deserialise a Blocked object that is associated with a Job whose
JobClass has a non-NULL session.
* init/tests/test_state. c: test_blocking(): Revert test to assert that
blocked job with non-NULL session is ignored. - 1483. By James Hunt
-
* init/state.c: stateful_reexec(): Specify all values for array
initialiser.
Stéphane Graber (stgraber) wrote : | # |
Steve Langasek (vorlon) wrote : | # |
After the merge of lp:~mdeslaur/upstart/apparmor-support, this no longer merges cleanly into trunk; and the conflicts in init/tests/
Steve Langasek (vorlon) wrote : | # |
On Mon, May 27, 2013 at 06:02:26PM -0000, Stéphane Graber wrote:
> Something looks wrong with this branch, commit 1481 should probably have
> been a rebase instead of merging trunk into a branch that you then want to
> merge into trunk. BZR won't fail to merge this but the history will look
> a bit weird.
No, merging trunk to the branch is the expected action here.
- 1484. By James Hunt
-
* Sync with lp:upstart.
* init/tests/test_state. c: test_upstart_ pre_security_ upgrade( ): Tweaks
to work with new TestDataFile structure and requirement that no
conf_sources exist just prior to deserialisation.
James Hunt (jamesodhunt) wrote : | # |
Re-synced with lp:upstart.
Steve Langasek (vorlon) wrote : | # |
--- init/event_
+++ init/event_
[...]
+event_
+ __attribute__ ((warn_
+
+NIH_END_EXTERN
+
char *event_
- __attribute__ ((warn_
-
-NIH_END_EXTERN
+ __attribute__ ((warn_
This moves the event_operator_
--- init/job_class.c 2013-05-15 13:21:54 +0000
+++ init/job_class.c 2013-05-30 17:07:37 +0000
@@ -1910,17 +2015,17 @@
- /* No object returned means the class doesn't need to be
- * serialised. Even if this is a real failure, it's always
- * better to serialise as much of the state as possible.
- */
if (! json_class)
- continue;
+ goto error;
I think the reasoning in that comment still holds (that it's better to serialize as much of the state as possible). But this is consistent with the behavior in the rest of the code, so I suppose that shouldn't be a blocker.
--- init/state.c 2013-02-28 16:40:36 +0000
+++ init/state.c 2013-05-30 17:07:37 +0000
[...]
+ /* Again, we cannot error here since older JSON state data did
+ * not encode ConfSource or ConfFile objects.
+ */
+ if (conf_source_
+ nih_warn ("%s", _("No ConfSources present in state data"));
Wouldn't it make sense to have a check on the format version, and make this an error for new formats vs. a warning for the old format?
So given that there are version checks now in the deserializer, and there is another change to the serialization format landing upstream at the same time: how can we backport this change to raring in an SRU? Should we consider the format with apparmor_switch to be version 4, and treat the confsource serialization without apparmor_switch to be version 3, then include tests for each (i.e., change
test_upstart_
Finally, it appears that there is no test json for the *current* serialization format. This should definitely be included as its own test, and added to the tree now - not be left until the next time someone changes the serialization format (or accidentally changes the deserializer!).
Other than that, this looks very good. If you can fix up the above issues, I'll approve this.
- 1485. By James Hunt
-
* init/event.c: event_deseriali
se(): Revert to checking JSON for
blockers to avoid reliance on JSON serialisation data format version.
* init/event_operator. h: Fix misplacement of NIH_END_EXTERN.
* init/state.c: Remove serialisation version code since the autoconf
approach of detecting the format of the JSON is safer.
* init/state.h: Remove STATE_VERSION. - 1486. By James Hunt
-
* init/tests/
data/upstart- 1.8+apparmor. json: New test data file.
* init/tests/test_state. c:
- test_upgrade(): Re-initialise lists and hashes as a convenience to
the tests.
- test_upstart_with_apparmor_ upgrade( ): New test to ensure Upstart can
parse the current 1.8 format JSON with the addition of the AppArmor
serialisation (but crucially *without* the full serialisation data
(EventOperator, etc).
- test_upstart_full_serialise_ without_ apparmor_ upgrade( ): New test to
ensure Upstart can parse the current 1.8 format JSON with the
addition of the full serialisation data (EventOperator, etc),
but _without_ the AppArmor serialisation.
James Hunt (jamesodhunt) wrote : | # |
The plan now is to remove the STATE_VERSION code and revert to the autoconf approach of detecting the format of the serialisation data by inspection (this also allows us to work around the backport issue without having to invent mythical format version numbers or other such games).
What we do need to do is add explicit tests for the serialisation formats shown below to allow full serialisation to be backported into Ubuntu _without_ the AppArmor branch (since the former is a fix whilst the latter is a new feature):
1) Current serialisation format with the addition of apparmor data, but without the full serialisation provided by this branch.
2) Current serialisation format with the addition of apparmor data, but without the full serialisation provided by this branch.
- 1487. By James Hunt
-
* init/tests/
data/upstart- 1.8+full_ serialisation+ apparmor. json: New test
data file.
* init/tests/test_state. c:
- test_upstart_full_serialise_ with_apparmor_ upgrade( ): New test to ensure
Upstart can parse the current 1.8 format JSON with the addition of the full
serialisation data (EventOperator, etc), and the AppArmor serialisation. - 1488. By James Hunt
-
* init/state.c: state_from_
string( ): Check if ConfSources
exist in the serialisation data to allow distinction between
ConfSources not present and failing to deserialise them. - 1489. By James Hunt
-
* Sync with lp:upstart.
Preview Diff
1 | === modified file 'ChangeLog' |
2 | --- ChangeLog 2013-05-31 15:57:47 +0000 |
3 | +++ ChangeLog 2013-06-05 16:21:24 +0000 |
4 | @@ -1,3 +1,38 @@ |
5 | +2013-06-05 James Hunt <james.hunt@ubuntu.com> |
6 | + |
7 | + * init/tests/data/upstart-1.8+apparmor.json: New test data file. |
8 | + * init/tests/data/upstart-1.8+full_serialisation-apparmor.json: |
9 | + New test data file. |
10 | + * init/tests/data/upstart-1.8+full_serialisation+apparmor.json: |
11 | + New test data file. |
12 | + * init/tests/test_state.c: |
13 | + - test_upgrade(): Re-initialise lists and hashes as a convenience to |
14 | + the tests. |
15 | + - test_upstart_with_apparmor_upgrade(): New test to ensure Upstart can |
16 | + parse the current 1.8 format JSON with the addition of the AppArmor |
17 | + serialisation (but crucially *without* the full serialisation data |
18 | + (EventOperator, etc). |
19 | + - test_upstart_full_serialise_without_apparmor_upgrade(): New test to |
20 | + ensure Upstart can parse the current 1.8 format JSON with the |
21 | + addition of the full serialisation data (EventOperator, etc), |
22 | + but _without_ the AppArmor serialisation. |
23 | + - test_upstart_full_serialise_with_apparmor_upgrade(): New test to |
24 | + ensure Upstart can parse the current 1.8 format JSON with the |
25 | + addition of the full serialisation data (EventOperator, etc), |
26 | + and the AppArmor serialisation. |
27 | + * init/state.c: state_from_string(): Check if ConfSources |
28 | + exist in the serialisation data to allow distinction between |
29 | + ConfSources not present and failing to deserialise them. |
30 | + |
31 | +2013-06-04 James Hunt <james.hunt@ubuntu.com> |
32 | + |
33 | + * init/event.c: event_deserialise(): Revert to checking JSON for |
34 | + blockers to avoid reliance on JSON serialisation data format version. |
35 | + * init/event_operator.h: Fix misplacement of NIH_END_EXTERN. |
36 | + * init/state.c: Remove serialisation version code since the autoconf |
37 | + approach of detecting the format of the JSON is safer. |
38 | + * init/state.h: Remove STATE_VERSION. |
39 | + |
40 | 2013-05-31 James Hunt <james.hunt@ubuntu.com> |
41 | |
42 | [ Eric S. Raymond <esr@thyrsus.com> ] |
43 | @@ -63,11 +98,250 @@ |
44 | * init/tests/test_state.c: Test apparmor_switch and |
45 | PROCESS_SECURITY. |
46 | |
47 | +2013-05-13 James Hunt <james.hunt@ubuntu.com> |
48 | + |
49 | + * init/state.c: stateful_reexec(): Specify all values for array |
50 | + initialiser. |
51 | + |
52 | +2013-05-10 James Hunt <james.hunt@ubuntu.com> |
53 | + |
54 | + Revert to not supporting deserialisation of JobClasses with associated |
55 | + user/chroot sessions to avoid behavioural change for now. |
56 | + |
57 | + * init/job_class.c: |
58 | + - job_class_deserialise(): Revert to failing if associated session is |
59 | + non-NULL. |
60 | + - job_class_deserialise_all(): Revert to ignoring failure to |
61 | + deserialise a JobClass iff it has a non-NULL associated session. |
62 | + * init/state.c: |
63 | + - state_to_string(): Provide some diagnostics if serialisation fails. |
64 | + - state_from_string(): Provide some diagnostics if deserialisation fails. |
65 | + - state_deserialise_resolve_deps(): Ignore failure to lookup JobClass |
66 | + iff it has an associated user/chroot session. |
67 | + - state_deserialise_blocking(): Revert to ignoring failure to |
68 | + deserialise a Blocked object that is associated with a Job whose |
69 | + JobClass has a non-NULL session. |
70 | + * init/tests/test_state.c: test_blocking(): Revert test to assert that |
71 | + blocked job with non-NULL session is ignored. |
72 | + |
73 | +2013-05-09 James Hunt <james.hunt@ubuntu.com> |
74 | + |
75 | + * init/job.c: job_serialise(): Corrected logic for handling 'stop on' |
76 | + condition. |
77 | + * init/job_class.c: job_class_deserialise(): Only check type after JSON |
78 | + queried (thanks Coverity). |
79 | + |
80 | +2013-05-08 James Hunt <james.hunt@ubuntu.com> |
81 | + |
82 | + * init/Makefile.am: Link test_util to test_event_operator. |
83 | + * init/conf.c: conf_source_deserialise_all(): Assert conf_sources is |
84 | + empty. |
85 | + * init/control.h: control_get_job(): Use job_class_get_registered() |
86 | + rather than redundant job_class_find(). |
87 | + * init/event_operator.c: |
88 | + - Typos and formatting. |
89 | + - event_operator_serialise(): Conditionally encode name and env. |
90 | + - event_operator_deserialise(): Treat env as a string array, not an |
91 | + environ array to ensure values are not discarded unless they contain '='. |
92 | + * init/job.c: |
93 | + - job_deserialise(): Check JSON type for 'stop on' prior to attempting value extraction. |
94 | + - job_find(): |
95 | + - Make job_class const. |
96 | + - Use job_class_get_registered() rather than job_class_find(). |
97 | + * init/job_class.c: |
98 | + - job_class_get_registered(): Rework. |
99 | + - job_class_add_safe(): Re-add since required to support old |
100 | + serialisation formats that do not encode ConfSource and ConfFile |
101 | + objects. |
102 | + - job_class_deserialise(): |
103 | + - Take care to only associate ConfFile with JobClass if JSON encodes |
104 | + ConfFile objects. |
105 | + - Check JSON type for 'start/stop on' prior to attempting value extraction. |
106 | + - job_class_find(): Remove (redundant due to job_class_get_registered()). |
107 | + * init/state.c: |
108 | + - Set serialisation_version to an invalid value to detect if it was |
109 | + never set (to handle old serialisation formats). |
110 | + - state_from_string(): |
111 | + - Make failure to read header and ConfSources warnings only, to support old |
112 | + serialisation formats that do not encode this information. |
113 | + - state_deserialise_blocked(): Fix bug where event blocker was being |
114 | + incremented twice. Now, just assert it is set. |
115 | + - state_deserialise_blocking(): Failure to deserialise a Blocked object |
116 | + is no longer ignored since sessions are supported. |
117 | + * init/state.h: STATE_VERSION history and notes. |
118 | + * init/tests/test_conf.c: Replace calls to job_class_find() with |
119 | + job_class_get_registered(). |
120 | + * init/tests/test_event_operator.c: |
121 | + - test_operator_serialisation(): Check both the original string |
122 | + serialisation format and the new full EventOperator serialisation. |
123 | + type. |
124 | + * init/tests/test_job.c: |
125 | + - test_deserialise_ptrace(): |
126 | + - Comments and more checks. |
127 | + - Create ConfSource, ConfFile and JobClass manually. |
128 | + - Call job_class_consider() as we now have a backing ConfFile. |
129 | + - Wait for childs child. |
130 | + * init/tests/test_state.c: |
131 | + - Simplify TestDataFile. |
132 | + - Ensure files passed to conf_file_new() provide expected suffix. |
133 | + - job_class_diff(): Add event_operator_diff() call. |
134 | + - conf_source_diff(): New function. |
135 | + - conf_file_diff(): New function. |
136 | + - test_blocking(): |
137 | + - Extra checks. |
138 | + - Expect ConfFiles to be recreated on re-exec. |
139 | + - test_upgrade(): Check environment is clean before running the next test. |
140 | + - test_upstart1_8_upgrade(): New Upstart-1.8 serialisation format test. |
141 | + - conf_source_from_path(): New utility function. |
142 | + * init/tests/test_util.c: |
143 | + - event_operator_diff(): New function. |
144 | + - session_from_chroot(): New function. |
145 | + * init/tests/data/upstart-1.8.json: New test file. |
146 | + |
147 | +2013-05-08 James Hunt <james.hunt@ubuntu.com> |
148 | + |
149 | + * init/conf.c: |
150 | + - conf_source_serialise_all(): Make failures fatal. |
151 | + * init/event_operator.c: event_operator_collapse(): Unhide but mark as |
152 | + unused (it's still used by the tests). |
153 | + * init/job.c: |
154 | + - job_serialise(): Remove unused variable. |
155 | + - job_deserialise(): Check the type of the start/stop on condition in |
156 | + the json, not the json passed to the function. |
157 | + * init/job_class.c: job_class_deserialise(): Check the type of the |
158 | + start/stop on condition in the json, not the json passed to the |
159 | + function. |
160 | + * init/state.c: |
161 | + - Comments. |
162 | + - state_read_header(): Extract header from JSON before checking for |
163 | + serialisation version. |
164 | + |
165 | 2013-05-07 James Hunt <james.hunt@ubuntu.com> |
166 | |
167 | * util/man/shutdown.8: Specify default action is to bring system |
168 | down to single-user mode (LP: #1065851). |
169 | |
170 | +2013-05-02 James Hunt <james.hunt@ubuntu.com> |
171 | + |
172 | + * init/event.c: event_deserialise(): Only set blockers if EventOperators |
173 | + are serialised. |
174 | + * init/event_operator.c: event_operator_collapse(): Now only needed for |
175 | + DEBUG. |
176 | + * init/job.c: |
177 | + - job_deserialise(): Support old string format for 'stop_on' |
178 | + EventOperator as well as new array format. |
179 | + * init/job_class.c: |
180 | + * init/state.c: Create a meta-header containing a serialisation version |
181 | + number. |
182 | + |
183 | +2013-05-02 James Hunt <james.hunt@ubuntu.com> |
184 | + |
185 | + * init/conf.c: |
186 | + - New serialisation and support functions: |
187 | + - conf_source_serialise() |
188 | + - conf_source_serialise_all() |
189 | + - conf_source_deserialise() |
190 | + - conf_source_deserialise_all() |
191 | + - conf_source_type_enum_to_str() |
192 | + - conf_source_type_str_to_enum() |
193 | + - conf_file_serialise() |
194 | + - conf_file_deserialise() |
195 | + - conf_file_deserialise_all() |
196 | + - conf_source_get_index() |
197 | + - conf_file_find() |
198 | + - debug_show_event_operator() |
199 | + - debug_show_event_operators() |
200 | + * init/event_operator.c: |
201 | + - event_deserialise(): |
202 | + - Fix leaked env array. |
203 | + - Deserialise blockers count now EventOperators are also serialised. |
204 | + - event_operator_type_enum_to_str() |
205 | + - event_operator_type_str_to_enum() |
206 | + - event_operator_serialise() |
207 | + - event_operator_serialise_all() |
208 | + - event_operator_deserialise() |
209 | + - event_operator_deserialise_all() |
210 | + * init/job_class.c: |
211 | + - job_class_add_safe(): Remove as no longer required. |
212 | + - job_class_get(): Must call job_class_init(). |
213 | + - job_class_serialise(): |
214 | + - Remove error case if chroot session specified now that ConfSources |
215 | + are serialised. |
216 | + - Serialise start/stop on fully (as EventOperators) rather than just the original |
217 | + string condition (LP: #1103881). |
218 | + - job_class_deserialise(): |
219 | + - Remove error case if chroot session specified now that ConfSources |
220 | + are serialised. |
221 | + - Associate the JobClass with its ConfFile. |
222 | + - job_class_serialise_all(): |
223 | + - Comments. |
224 | + - Failure to serialise a JobClass is now a hard error since we now |
225 | + serialise all JobClasses. |
226 | + - job_class_deserialise(): |
227 | + - Deserialise start/stop on conditions as EventOperators rather than as a |
228 | + string condition. |
229 | + - Since ConfFiles are now serialised, call job_class_consider() |
230 | + rather than job_class_add_safe(). |
231 | + - job_class_deserialise_all(): |
232 | + - Failure to deserialise a JobClass is now a hard error since we now |
233 | + serialise all JobClasses. |
234 | + - job_class_get_index(): New function. |
235 | + * init/state.c: |
236 | + - state_to_string(): Serialise ConfSources and ConfFiles. |
237 | + - state_from_string(): Deserialise ConfSources and ConfFiles. |
238 | + - state_deserialise_resolve_deps(): Allow chroot sessions to be |
239 | + handled now we serialise ConfSources and ConfFiles. |
240 | + |
241 | +2013-04-30 James Hunt <james.hunt@ubuntu.com> |
242 | + |
243 | + * init/job.c: job_serialise_all(): Really serialise all JobClasses, |
244 | + * init/main.c: Add 'write-state-file' command-line option. |
245 | + regardless of whether they have associated Jobs. |
246 | + * init/paths.h: Added STATE_FILE_ENV. |
247 | + * init/state.c: |
248 | + - state_read_objects(): Write state file if 'write-state-file' |
249 | + specified or STATE_FILE_ENV set. |
250 | + - event_deserialise(): |
251 | + - Preserve the pre-reexec blockers count until JobClasses |
252 | + are deserialised and reverse-dependencies resolved. |
253 | + - Fix incorrect calls for failed and blockers Event attributes. |
254 | + * init/state.h: Comments. |
255 | + * init/tests/test_state.c: |
256 | + - test_job_class_serialise(): Ensure that all JobClasses get |
257 | + serialised, regardless of whether they have any associated |
258 | + Jobs. |
259 | + - test_event_serialise(): New "with failed" test. |
260 | + * init/event.c: event_deserialise(): Don't deserialise Event->blockers - |
261 | + there is no point until we serialise EventOperators. |
262 | + |
263 | +2013-04-29 James Hunt <james.hunt@ubuntu.com> |
264 | + |
265 | + * init/conf.c: |
266 | + - conf_reload(): Explanation of how reload works. |
267 | + - conf_reload_path(): Defer destruction of original ConfFile until |
268 | + newly-loaded .conf file has a chance to reference any events its |
269 | + 'start on' condition requires (LP: 1124384). |
270 | + - debug_show_jobs(): Return if no instances. |
271 | + - debug_show_events(): New function. |
272 | + * init/event.c: Comments. |
273 | + * init/job.c: Comment. |
274 | + * init/job_class.c: |
275 | + - job_class_get_registered(): New function resulting from refactor of |
276 | + job_class_consider() and job_class_reconsider(). |
277 | + - job_class_consider(): |
278 | + - Use job_class_get_registered(). |
279 | + - Call job_class_event_block() to avoid premature event destruction. |
280 | + - job_class_reconsider(): Use job_class_get_registered(). |
281 | + - job_class_event_block(): New function to increase reference count |
282 | + for events new JobClass specifies in its 'start on' condition that |
283 | + old JobClass has also referenced (second part of LP: #1124384). |
284 | + * init/tests/test_conf.c: |
285 | + - test_source_reload(): New tests: |
286 | + - "ensure reload does not destroy a blocked event used by another job" |
287 | + - "ensure .conf reload causes waiting job to run when 'start on' matches" |
288 | + * init/tests/test_conf.h: TEST_ENSURE_CLEAN_ENV(): Check |
289 | + nih_child_watches too. |
290 | + |
291 | 2013-04-22 James Hunt <james.hunt@ubuntu.com> |
292 | |
293 | * Typo and doc changes. |
294 | |
295 | === modified file 'init/Makefile.am' |
296 | --- init/Makefile.am 2013-05-15 13:21:54 +0000 |
297 | +++ init/Makefile.am 2013-06-05 16:21:24 +0000 |
298 | @@ -280,7 +280,7 @@ |
299 | $(JSON_LIBS) \ |
300 | -lrt |
301 | |
302 | -test_event_operator_SOURCES = tests/test_event_operator.c |
303 | +test_event_operator_SOURCES = tests/test_event_operator.c $(test_util_SOURCES) |
304 | test_event_operator_LDADD = \ |
305 | system.o environ.o process.o \ |
306 | job_class.o job_process.o job.o event.o event_operator.o blocked.o \ |
307 | |
308 | === modified file 'init/conf.c' |
309 | --- init/conf.c 2013-02-27 11:46:04 +0000 |
310 | +++ init/conf.c 2013-06-05 16:21:24 +0000 |
311 | @@ -2,7 +2,7 @@ |
312 | * |
313 | * conf.c - configuration management |
314 | * |
315 | - * Copyright © 2009,2010,2011,2012,2013 Canonical Ltd. |
316 | + * Copyright 2009,2010,2011,2012,2013 Canonical Ltd. |
317 | * Author: Scott James Remnant <scott@netsplit.com>. |
318 | * |
319 | * This program is free software; you can redistribute it and/or modify |
320 | @@ -49,6 +49,7 @@ |
321 | #include "conf.h" |
322 | #include "errors.h" |
323 | #include "paths.h" |
324 | +#include "environ.h" |
325 | |
326 | /* Prototypes for static functions */ |
327 | static int conf_source_reload_file (ConfSource *source) |
328 | @@ -103,6 +104,7 @@ |
329 | **/ |
330 | NihList *conf_sources = NULL; |
331 | |
332 | +extern json_object *json_conf_sources; |
333 | |
334 | /** |
335 | * is_conf_file_std: |
336 | @@ -447,12 +449,24 @@ |
337 | /** |
338 | * conf_reload: |
339 | * |
340 | - * Reloads all configuration sources. |
341 | + * Reloads configuration sources. |
342 | * |
343 | * Watches on new configuration sources are established so that future |
344 | * changes will be automatically detected with inotify. Then for both |
345 | * new and existing sources, the current state is parsed. |
346 | * |
347 | + * All ConfFiles are recreated as part of the reload. If the JobClass |
348 | + * associated with a ConfSource has no Job instances, the JobClass is |
349 | + * recreated and added to the job_classes hash. |
350 | + * |
351 | + * However, if a JobClass has running instances at reload time, although |
352 | + * a new ConfSource *and* a new JobClass are created, the new JobClass |
353 | + * (called the "best") will *NOT* be added to the job_classes hash until |
354 | + * the last running instance has finished. At this point, the "registered" |
355 | + * JobClass will be removed from the hash (when job_class_reconsider() |
356 | + * is called by job_change_state()) and replaced by the "best" (newest) |
357 | + * JobClass. |
358 | + * |
359 | * Any errors are logged through the usual mechanism, and not returned, |
360 | * since some configuration may have been parsed; and it's possible to |
361 | * parse no configuration without error. |
362 | @@ -1039,6 +1053,7 @@ |
363 | const char *override_path) |
364 | { |
365 | ConfFile *file = NULL; |
366 | + ConfFile *orig = NULL; |
367 | nih_local char *buf = NULL; |
368 | nih_local char *name = NULL; |
369 | size_t len, pos, lineno; |
370 | @@ -1051,25 +1066,67 @@ |
371 | path_to_load = (override_path ? override_path : path); |
372 | |
373 | /* If there is no corresponding override file, look up the old |
374 | - * conf file in memory, and then free it. In cases of failure, |
375 | + * conf file in memory, and then free it. In cases of failure, |
376 | * we discard it anyway, so there's no particular reason |
377 | * to keep it around anymore. |
378 | * |
379 | - * Note: if @override_path has been specified, do not |
380 | - * free the file if found, since we want to _update_ the |
381 | - * existing entry. |
382 | + * Notes: |
383 | + * |
384 | + * - If @override_path has been specified, do not free the file |
385 | + * if found, since we want to _update_ the existing entry. |
386 | + * - Freeing a ConfFile does _not_ necessarily free its associated |
387 | + * JobClass. |
388 | */ |
389 | - file = (ConfFile *)nih_hash_lookup (source->files, path); |
390 | - if (! override_path && file) |
391 | - nih_unref (file, source); |
392 | + orig = (ConfFile *)nih_hash_lookup (source->files, path); |
393 | + if (! override_path && orig) { |
394 | + /* Found an existing ConfFile. We will free this, but |
395 | + * just not yet since iff that ConfFiles associated JobClass |
396 | + * does not have any running instances, freeing the |
397 | + * ConfFile will cause the original JobClass associated |
398 | + * with this ConfFile to be destroyed. But if the JobClass |
399 | + * had referenced any events via it's 'start on' EventOperator tree, |
400 | + * the JobClasses destruction could lead to the Events |
401 | + * being destroyed _before_ the about-to-be-created |
402 | + * replacement JobClass gets a chance to reference those |
403 | + * same events (assuming its 'start on' EventOperator tree |
404 | + * contains nodes specifying the same event names as |
405 | + * those in the original JobClasses). |
406 | + * |
407 | + * As such, we simply remove the ConfFile from its |
408 | + * parent ConfSources hash, create the new ConfFile and |
409 | + * JobClass, give the new JobClass a chance to be the |
410 | + * registered JobClass, and finally allow the original |
411 | + * ConfFile to be destroyed. |
412 | + * |
413 | + * If this is not done, reloading a configuration |
414 | + * mid-way through the boot sequence could lead to a |
415 | + * hung system as the new JobClasses will wait forever |
416 | + * for events to be emitted that have already been |
417 | + * destroyed. |
418 | + */ |
419 | + nih_list_remove (&orig->entry); |
420 | + } |
421 | |
422 | /* Read the file into memory for parsing, if this fails we don't |
423 | * bother creating a new ConfFile structure for it and bail out |
424 | * now. |
425 | */ |
426 | buf = nih_file_read (NULL, path_to_load, &len); |
427 | - if (! buf) |
428 | + if (! buf) { |
429 | + if (! override_path && orig) { |
430 | + /* Failed to reload the file from disk in all |
431 | + * likelihood because the configuration file was |
432 | + * deleted. |
433 | + * |
434 | + * Allow the ConfFile to be cleaned up taking |
435 | + * its JobClass (and possibly events that |
436 | + * JobClass was referencing) with it. |
437 | + */ |
438 | + nih_unref (orig, source); |
439 | + } |
440 | + |
441 | return -1; |
442 | + } |
443 | |
444 | /* Create a new ConfFile structure (if no @override_path specified) */ |
445 | file = (ConfFile *)nih_hash_lookup (source->files, path); |
446 | @@ -1112,6 +1169,10 @@ |
447 | file->job = parse_job (NULL, source->session, file->job, |
448 | name, buf, len, &pos, &lineno); |
449 | |
450 | + /* Allow the original ConfFile which has now been replaced to be |
451 | + * destroyed which will also cause the original JobClass to be |
452 | + * freed. |
453 | + */ |
454 | if (file->job) { |
455 | job_class_consider (file->job); |
456 | } else { |
457 | @@ -1123,6 +1184,12 @@ |
458 | nih_assert_not_reached (); |
459 | } |
460 | |
461 | + /* Finally, allow the original ConfFile to be destroyed without |
462 | + * affecting the new JobClass. |
463 | + */ |
464 | + if (! override_path && orig) |
465 | + nih_unref (orig, source); |
466 | + |
467 | /* Deal with any parsing errors that occurred; we don't consider |
468 | * these to be hard failures, which means we can warn about them |
469 | * here and give the path and line number along with the warning. |
470 | @@ -1253,8 +1320,568 @@ |
471 | return NULL; |
472 | } |
473 | |
474 | +/** |
475 | + * conf_source_serialise: |
476 | + * @source: ConfSource to serialise. |
477 | + * |
478 | + * Convert @source into a JSON representation for serialisation. |
479 | + * Caller must free returned value using json_object_put(). |
480 | + * |
481 | + * Returns: JSON-serialised ConfSource object, or NULL on error. |
482 | + **/ |
483 | +json_object * |
484 | +conf_source_serialise (const ConfSource *source) |
485 | +{ |
486 | + json_object *json; |
487 | + json_object *json_files; |
488 | + int session_index; |
489 | + |
490 | + nih_assert (source); |
491 | + nih_assert (conf_sources); |
492 | + |
493 | + json = json_object_new_object (); |
494 | + if (! json) |
495 | + return NULL; |
496 | + |
497 | + json_files = json_object_new_array (); |
498 | + if (! json_files) |
499 | + goto error; |
500 | + |
501 | + session_index = session_get_index (source->session); |
502 | + if (session_index < 0) |
503 | + goto error; |
504 | + |
505 | + if (! state_set_json_int_var (json, "session", session_index)) |
506 | + goto error; |
507 | + |
508 | + if (! state_set_json_string_var_from_obj (json, source, path)) |
509 | + goto error; |
510 | + |
511 | + if (! state_set_json_enum_var (json, |
512 | + conf_source_type_enum_to_str, |
513 | + "type", source->type)) |
514 | + goto error; |
515 | + |
516 | + /* 'watch' does not need to be serialised - it gets recreated |
517 | + * when conf_source_new() is called on deserialisation. |
518 | + */ |
519 | + |
520 | + if (! state_set_json_int_var_from_obj (json, source, flag)) |
521 | + goto error; |
522 | + |
523 | + /* Add array of ConfFile names to represent the files hash */ |
524 | + NIH_HASH_FOREACH (source->files, file_iter) { |
525 | + ConfFile *file = (ConfFile *)file_iter; |
526 | + json_object *json_conf_file; |
527 | + |
528 | + json_conf_file = conf_file_serialise (file); |
529 | + if (! json_conf_file) |
530 | + goto error; |
531 | + |
532 | + json_object_array_add (json_files, json_conf_file); |
533 | + } |
534 | + |
535 | + json_object_object_add (json, "conf_files", json_files); |
536 | + |
537 | + return json; |
538 | + |
539 | +error: |
540 | + json_object_put (json); |
541 | + return NULL; |
542 | +} |
543 | + |
544 | +/** |
545 | + * conf_source_serialise_all: |
546 | + * |
547 | + * Convert existing ConfSource objects to JSON representation. |
548 | + * |
549 | + * Returns: JSON object containing array of ConfSource objects, |
550 | + * or NULL on error. |
551 | + **/ |
552 | +json_object * |
553 | +conf_source_serialise_all (void) |
554 | +{ |
555 | + json_object *json; |
556 | + |
557 | + conf_init (); |
558 | + |
559 | + json = json_object_new_array (); |
560 | + if (! json) |
561 | + return NULL; |
562 | + |
563 | + NIH_LIST_FOREACH (conf_sources, iter) { |
564 | + json_object *json_source; |
565 | + ConfSource *source = (ConfSource *)iter; |
566 | + |
567 | + json_source = conf_source_serialise (source); |
568 | + |
569 | + if (! json_source) |
570 | + goto error; |
571 | + |
572 | + json_object_array_add (json, json_source); |
573 | + } |
574 | + |
575 | + return json; |
576 | + |
577 | +error: |
578 | + json_object_put (json); |
579 | + return NULL; |
580 | +} |
581 | + |
582 | +/** |
583 | + * conf_source_deserialise: |
584 | + * @parent: parent, |
585 | + * @json: JSON-serialised ConfSource object to deserialise. |
586 | + * |
587 | + * Create ConfSource from provided JSON and add to the |
588 | + * conf sources list. |
589 | + * |
590 | + * Returns: ConfSource object, or NULL on error. |
591 | + **/ |
592 | +ConfSource * |
593 | +conf_source_deserialise (void *parent, json_object *json) |
594 | +{ |
595 | + ConfSource *source = NULL; |
596 | + ConfSourceType type = -1; |
597 | + Session *session; |
598 | + int session_index = -1; |
599 | + nih_local char *path = NULL; |
600 | + |
601 | + nih_assert (json); |
602 | + |
603 | + if (! state_check_json_type (json, object)) |
604 | + goto error; |
605 | + |
606 | + if (! state_get_json_int_var (json, "session", session_index)) |
607 | + goto error; |
608 | + |
609 | + if (session_index < 0) |
610 | + goto error; |
611 | + |
612 | + session = session_from_index (session_index); |
613 | + |
614 | + if (! state_get_json_string_var_strict (json, "path", NULL, path)) |
615 | + goto error; |
616 | + |
617 | + if (! state_get_json_enum_var (json, |
618 | + conf_source_type_str_to_enum, |
619 | + "type", type)) |
620 | + goto error; |
621 | + |
622 | + source = conf_source_new (parent, path, type); |
623 | + if (! source) |
624 | + goto error; |
625 | + |
626 | + source->session = session; |
627 | + |
628 | + if (! state_get_json_int_var_to_obj (json, source, flag)) |
629 | + goto error; |
630 | + |
631 | + if (conf_file_deserialise_all (source, json) < 0) |
632 | + goto error; |
633 | + |
634 | + return source; |
635 | + |
636 | +error: |
637 | + if (source) |
638 | + nih_free (source); |
639 | + |
640 | + return NULL; |
641 | +} |
642 | + |
643 | +/** |
644 | + * conf_source_deserialise_all: |
645 | + * |
646 | + * @json: root of JSON-serialised state. |
647 | + * |
648 | + * Convert JSON representation of ConfSources back into ConfSource objects. |
649 | + * |
650 | + * Returns: 0 on success, -1 on error. |
651 | + **/ |
652 | +int |
653 | +conf_source_deserialise_all (json_object *json) |
654 | +{ |
655 | + ConfSource *source = NULL; |
656 | + |
657 | + nih_assert (json); |
658 | + |
659 | + conf_init (); |
660 | + |
661 | + nih_assert (NIH_LIST_EMPTY (conf_sources)); |
662 | + |
663 | + json_conf_sources = json_object_object_get (json, "conf_sources"); |
664 | + |
665 | + if (! json_conf_sources) |
666 | + goto error; |
667 | + |
668 | + if (! state_check_json_type (json_conf_sources, array)) |
669 | + goto error; |
670 | + |
671 | + for (int i = 0; i < json_object_array_length (json_conf_sources); i++) { |
672 | + json_object *json_source; |
673 | + |
674 | + json_source = json_object_array_get_idx (json_conf_sources, i); |
675 | + if (! json_source) |
676 | + goto error; |
677 | + |
678 | + if (! state_check_json_type (json_source, object)) |
679 | + goto error; |
680 | + |
681 | + source = conf_source_deserialise (NULL, json_source); |
682 | + |
683 | + if (! source) |
684 | + continue; |
685 | + } |
686 | + |
687 | + return 0; |
688 | + |
689 | +error: |
690 | + if (source) |
691 | + nih_free (source); |
692 | + |
693 | + return -1; |
694 | +} |
695 | + |
696 | +/** |
697 | + * conf_source_type_enum_to_str: |
698 | + * |
699 | + * @type: ConfSourceType. |
700 | + * |
701 | + * Convert ConfSourceType to a string representation. |
702 | + * |
703 | + * Returns: string representation of @type, or NULL if not known. |
704 | + **/ |
705 | +const char * |
706 | +conf_source_type_enum_to_str (ConfSourceType type) |
707 | +{ |
708 | + state_enum_to_str (CONF_FILE, type); |
709 | + state_enum_to_str (CONF_DIR, type); |
710 | + state_enum_to_str (CONF_JOB_DIR, type); |
711 | + |
712 | + return NULL; |
713 | +} |
714 | + |
715 | +/** |
716 | + * conf_source_type_str_to_enum: |
717 | + * |
718 | + * @type: string ConfSourceType value. |
719 | + * |
720 | + * Convert @expect back into an enum value. |
721 | + * |
722 | + * Returns: ConfSourceType representing @type, or -1 if not known. |
723 | + **/ |
724 | +ConfSourceType |
725 | +conf_source_type_str_to_enum (const char *type) |
726 | +{ |
727 | + nih_assert (type); |
728 | + |
729 | + state_str_to_enum (CONF_FILE, type); |
730 | + state_str_to_enum (CONF_DIR, type); |
731 | + state_str_to_enum (CONF_JOB_DIR, type); |
732 | + |
733 | + return -1; |
734 | +} |
735 | + |
736 | +/** |
737 | + * conf_file_serialise: |
738 | + * @file: ConfFile to serialise. |
739 | + * |
740 | + * Convert @file into a JSON representation for serialisation. |
741 | + * Caller must free returned value using json_object_put(). |
742 | + * |
743 | + * Returns: JSON-serialised ConfFile object, or NULL on error. |
744 | + **/ |
745 | +json_object * |
746 | +conf_file_serialise (const ConfFile *file) |
747 | +{ |
748 | + json_object *json; |
749 | + json_object *json_job_class; |
750 | + JobClass *registered; |
751 | + int session_index; |
752 | + ssize_t conf_source_index; |
753 | + |
754 | + nih_assert (file); |
755 | + |
756 | + json = json_object_new_object (); |
757 | + if (! json) |
758 | + return NULL; |
759 | + |
760 | + if (! state_set_json_string_var_from_obj (json, file, path)) |
761 | + goto error; |
762 | + |
763 | + conf_source_index = conf_source_get_index (file->source); |
764 | + if (conf_source_index < 0) |
765 | + goto error; |
766 | + |
767 | + if (! state_set_json_int_var (json, "conf_source", conf_source_index)) |
768 | + goto error; |
769 | + |
770 | + if (! state_set_json_int_var_from_obj (json, file, flag)) |
771 | + goto error; |
772 | + |
773 | + /* |
774 | + * Ignore the "best" JobClass associated with this ConfFile |
775 | + * (file->job) since it won't be serialised. |
776 | + * |
777 | + * Instead look up the currently registered JobClass and |
778 | + * reference that. This ensures that best == registered for the |
779 | + * re-exec. This may change though immediately after re-exec |
780 | + * when conf_reload() gets called. |
781 | + * |
782 | + * See job_class_serialise_all() for further details. |
783 | + */ |
784 | + registered = job_class_get_registered (file->job->name, |
785 | + file->job->session); |
786 | + |
787 | + if (! registered) |
788 | + goto error; |
789 | + |
790 | + /* Create a reference to the registered job class in the JSON by |
791 | + * encoding the name and session index. We do this rather than |
792 | + * simply encoding an index number for the JobClass since |
793 | + * job_classes is a hash and it is safer should a re-exec |
794 | + * result from an upgrade to NIH, say, where its hashing |
795 | + * algorithm changed meaning the index may be unreliable once |
796 | + * the job_classes hash was created post-re-exec. |
797 | + */ |
798 | + json_job_class = json_object_new_object (); |
799 | + if (! json_job_class) |
800 | + goto error; |
801 | + |
802 | + if (! state_set_json_string_var (json_job_class, |
803 | + "name", |
804 | + registered->name)) |
805 | + goto error; |
806 | + |
807 | + session_index = session_get_index (registered->session); |
808 | + if (session_index < 0) |
809 | + goto error; |
810 | + |
811 | + if (! state_set_json_int_var (json_job_class, |
812 | + "session", |
813 | + session_index)) |
814 | + goto error; |
815 | + |
816 | + json_object_object_add (json, "job_class", json_job_class); |
817 | + |
818 | + return json; |
819 | + |
820 | +error: |
821 | + json_object_put (json); |
822 | + return NULL; |
823 | +} |
824 | + |
825 | +/** |
826 | + * conf_file_deserialise: |
827 | + * @source: ConfSource, |
828 | + * @json: JSON-serialised ConfFile object to deserialise. |
829 | + * |
830 | + * Create ConfFile from provided JSON and add to the |
831 | + * conf sources list. |
832 | + * |
833 | + * Returns: ConfFile object, or NULL on error. |
834 | + **/ |
835 | +ConfFile * |
836 | +conf_file_deserialise (ConfSource *source, json_object *json) |
837 | +{ |
838 | + ConfFile *file = NULL; |
839 | + nih_local char *path = NULL; |
840 | + |
841 | + nih_assert (json); |
842 | + |
843 | + if (! state_check_json_type (json, object)) |
844 | + goto error; |
845 | + |
846 | + if (! state_get_json_string_var_strict (json, "path", NULL, path)) |
847 | + goto error; |
848 | + |
849 | + file = conf_file_new (source, path); |
850 | + if (! file) |
851 | + goto error; |
852 | + |
853 | + /* Note that the associated JobClass is not handled at this |
854 | + * stage: it can't be the JobClasses haven't been deserialised |
855 | + * yet. As such, the ConfFile->JobClass link is dealt with by |
856 | + * job_class_deserialise_all(). |
857 | + */ |
858 | + file->job = NULL; |
859 | + |
860 | + if (! state_get_json_int_var_to_obj (json, file, flag)) |
861 | + goto error; |
862 | + |
863 | + return file; |
864 | + |
865 | +error: |
866 | + if (file) |
867 | + nih_free (file); |
868 | + |
869 | + return NULL; |
870 | +} |
871 | + |
872 | +/** |
873 | + * conf_file_deserialise_all: |
874 | + * |
875 | + * @source: ConfSource, |
876 | + * @json: root of JSON-serialised state. |
877 | + * |
878 | + * Convert JSON representation of ConfFiles back into ConfFile objects. |
879 | + * |
880 | + * Returns: 0 on success, -1 on error. |
881 | + **/ |
882 | +int |
883 | +conf_file_deserialise_all (ConfSource *source, json_object *json) |
884 | +{ |
885 | + json_object *json_conf_files; |
886 | + ConfFile *file = NULL; |
887 | + |
888 | + nih_assert (source); |
889 | + nih_assert (json); |
890 | + |
891 | + conf_init (); |
892 | + |
893 | + json_conf_files = json_object_object_get (json, "conf_files"); |
894 | + |
895 | + if (! json_conf_files) |
896 | + goto error; |
897 | + |
898 | + if (! state_check_json_type (json_conf_files, array)) |
899 | + goto error; |
900 | + |
901 | + for (int i = 0; i < json_object_array_length (json_conf_files); i++) { |
902 | + json_object *json_file; |
903 | + |
904 | + json_file = json_object_array_get_idx (json_conf_files, i); |
905 | + if (! json_file) |
906 | + goto error; |
907 | + |
908 | + if (! state_check_json_type (json_file, object)) |
909 | + goto error; |
910 | + |
911 | + file = conf_file_deserialise (source, json_file); |
912 | + |
913 | + if (! file) |
914 | + goto error; |
915 | + } |
916 | + |
917 | + return 0; |
918 | + |
919 | +error: |
920 | + if (file) |
921 | + nih_free (file); |
922 | + |
923 | + return -1; |
924 | +} |
925 | + |
926 | +/** |
927 | + * conf_source_get_index: |
928 | + * |
929 | + * @source: ConfSource to search for. |
930 | + * |
931 | + * Returns: index of @source in the conf sources list, |
932 | + * or -1 if not found. |
933 | + **/ |
934 | +ssize_t |
935 | +conf_source_get_index (const ConfSource *source) |
936 | +{ |
937 | + ssize_t i = 0; |
938 | + |
939 | + nih_assert (source); |
940 | + |
941 | + conf_init (); |
942 | + |
943 | + NIH_LIST_FOREACH (conf_sources, iter) { |
944 | + ConfSource *s = (ConfSource *)iter; |
945 | + |
946 | + if (! strcmp (source->path, s->path) |
947 | + && source->session == s->session) |
948 | + return i; |
949 | + i++; |
950 | + } |
951 | + |
952 | + return -1; |
953 | +} |
954 | + |
955 | +/** |
956 | + * conf_file_find: |
957 | + * |
958 | + * @name: name of ConfFile (without dirname and extension), |
959 | + * @session: session ConfFile belongs to. |
960 | + * |
961 | + * Find the ConfFile with name @name in session @session. |
962 | + * |
963 | + * Returns: ConfFile or NULL if not found. |
964 | + **/ |
965 | +ConfFile * |
966 | +conf_file_find (const char *name, const Session *session) |
967 | +{ |
968 | + nih_local char *basename = NULL; |
969 | + |
970 | + nih_assert (name); |
971 | + |
972 | + conf_init (); |
973 | + |
974 | + /* There can only be one ConfFile per session with the same |
975 | + * basename. |
976 | + */ |
977 | + basename = NIH_MUST (nih_sprintf (NULL, "/%s%s", |
978 | + name, CONF_EXT_STD)); |
979 | + |
980 | + NIH_LIST_FOREACH (conf_sources, iter) { |
981 | + ConfSource *source = (ConfSource *)iter; |
982 | + |
983 | + if (source->session != session) |
984 | + continue; |
985 | + |
986 | + NIH_HASH_FOREACH (source->files, file_iter) { |
987 | + ConfFile *file = (ConfFile *)file_iter; |
988 | + char *match; |
989 | + char *slash; |
990 | + |
991 | + match = strstr (file->path, basename); |
992 | + slash = strrchr (file->path, '/'); |
993 | + |
994 | + if (match && match == slash) |
995 | + return file; |
996 | + } |
997 | + } |
998 | + |
999 | + return NULL; |
1000 | +} |
1001 | + |
1002 | #ifdef DEBUG |
1003 | |
1004 | +void |
1005 | +debug_show_event_operator (EventOperator *oper) |
1006 | +{ |
1007 | + nih_local char *env = NULL; |
1008 | + |
1009 | + nih_assert (oper); |
1010 | + |
1011 | + if (oper->env) env = state_collapse_env ((const char **)oper->env); |
1012 | + |
1013 | + nih_debug ("EventOperator %p: type='%s', value=%d, name='%s', event='%s', env='%s'", |
1014 | + oper, |
1015 | + oper->type == EVENT_MATCH ? "EVENT_MATCH" |
1016 | + : oper->type == EVENT_AND ? "EVENT_AND" |
1017 | + : "EVENT_OR", |
1018 | + oper->value, |
1019 | + oper->name, |
1020 | + oper->event ? oper->event->name : "", |
1021 | + env ? env : ""); |
1022 | +} |
1023 | + |
1024 | +void |
1025 | +debug_show_event_operators (EventOperator *root) |
1026 | +{ |
1027 | + nih_assert (root); |
1028 | + |
1029 | + NIH_TREE_FOREACH_POST (&root->node, iter) { |
1030 | + EventOperator *oper = (EventOperator *)iter; |
1031 | + |
1032 | + debug_show_event_operator (oper); |
1033 | + } |
1034 | +} |
1035 | + |
1036 | size_t |
1037 | debug_count_list_entries (const NihList *list) |
1038 | { |
1039 | @@ -1383,7 +2010,8 @@ |
1040 | void |
1041 | debug_show_jobs (const NihHash *instances) |
1042 | { |
1043 | - nih_assert (instances); |
1044 | + if (! instances) |
1045 | + return; |
1046 | |
1047 | nih_debug ("jobs:"); |
1048 | |
1049 | @@ -1405,6 +2033,18 @@ |
1050 | } |
1051 | |
1052 | void |
1053 | +debug_show_events (void) |
1054 | +{ |
1055 | + nih_assert (events); |
1056 | + |
1057 | + NIH_LIST_FOREACH (events, iter) { |
1058 | + Event *event = (Event *)iter; |
1059 | + |
1060 | + debug_show_event (event); |
1061 | + } |
1062 | +} |
1063 | + |
1064 | +void |
1065 | debug_show_conf_file (const ConfFile *file) |
1066 | { |
1067 | nih_assert (file); |
1068 | |
1069 | === modified file 'init/conf.h' |
1070 | --- init/conf.h 2013-02-27 11:46:04 +0000 |
1071 | +++ init/conf.h 2013-06-05 16:21:24 +0000 |
1072 | @@ -1,6 +1,6 @@ |
1073 | /* upstart |
1074 | * |
1075 | - * Copyright © 2010,2011 Canonical Ltd. |
1076 | + * Copyright 2010,2011 Canonical Ltd. |
1077 | * Author: Scott James Remnant <scott@netsplit.com>. |
1078 | * |
1079 | * This program is free software; you can redistribute it and/or modify |
1080 | @@ -128,6 +128,50 @@ |
1081 | |
1082 | JobClass * conf_select_job (const char *name, const Session *session); |
1083 | |
1084 | +const char * |
1085 | +conf_source_type_enum_to_str (ConfSourceType type) |
1086 | + __attribute__ ((warn_unused_result)); |
1087 | + |
1088 | +ConfSourceType |
1089 | +conf_source_type_str_to_enum (const char *type) |
1090 | + __attribute__ ((warn_unused_result)); |
1091 | + |
1092 | +json_object * |
1093 | +conf_source_serialise (const ConfSource *source) |
1094 | + __attribute__ ((warn_unused_result)); |
1095 | + |
1096 | +json_object * |
1097 | +conf_source_serialise_all (void) |
1098 | + __attribute__ ((warn_unused_result)); |
1099 | + |
1100 | +ConfSource * |
1101 | +conf_source_deserialise (void *parent, json_object *json) |
1102 | + __attribute__ ((warn_unused_result)); |
1103 | + |
1104 | +int |
1105 | +conf_source_deserialise_all (json_object *json) |
1106 | + __attribute__ ((warn_unused_result)); |
1107 | + |
1108 | +json_object * |
1109 | +conf_file_serialise (const ConfFile *file) |
1110 | + __attribute__ ((warn_unused_result)); |
1111 | + |
1112 | +ConfFile * |
1113 | +conf_file_deserialise (ConfSource *source, json_object *json) |
1114 | + __attribute__ ((warn_unused_result)); |
1115 | + |
1116 | +int |
1117 | +conf_file_deserialise_all (ConfSource *source, json_object *json) |
1118 | + __attribute__ ((warn_unused_result)); |
1119 | + |
1120 | +ssize_t |
1121 | +conf_source_get_index (const ConfSource *source) |
1122 | + __attribute__ ((warn_unused_result)); |
1123 | + |
1124 | +ConfFile * |
1125 | +conf_file_find (const char *name, const Session *session) |
1126 | + __attribute__ ((warn_unused_result)); |
1127 | + |
1128 | #ifdef DEBUG |
1129 | |
1130 | /* used for debugging only */ |
1131 | @@ -160,6 +204,10 @@ |
1132 | __attribute__ ((unused)); |
1133 | |
1134 | void |
1135 | +debug_show_events (void) |
1136 | + __attribute__ ((unused)); |
1137 | + |
1138 | +void |
1139 | debug_show_conf_file(const ConfFile *file) |
1140 | __attribute__ ((unused)); |
1141 | |
1142 | @@ -171,6 +219,14 @@ |
1143 | debug_show_conf_sources(void) |
1144 | __attribute__ ((unused)); |
1145 | |
1146 | +void |
1147 | +debug_show_event_operator (EventOperator *oper) |
1148 | + __attribute__ ((unused)); |
1149 | + |
1150 | +void |
1151 | +debug_show_event_operators (EventOperator *root) |
1152 | + __attribute__ ((unused)); |
1153 | + |
1154 | #endif |
1155 | |
1156 | NIH_END_EXTERN |
1157 | |
1158 | === modified file 'init/control.h' |
1159 | --- init/control.h 2013-02-08 16:15:23 +0000 |
1160 | +++ init/control.h 2013-06-05 16:21:24 +0000 |
1161 | @@ -58,31 +58,31 @@ |
1162 | * |
1163 | * Returns: -1 on raised error, or nothing on success. |
1164 | **/ |
1165 | -#define control_get_job(session, job, job_name, instance) \ |
1166 | -{ \ |
1167 | - if (job_name != NULL ) { \ |
1168 | - JobClass *class; \ |
1169 | - \ |
1170 | - class = job_class_find (session, job_name); \ |
1171 | - if (! class) { \ |
1172 | - nih_dbus_error_raise_printf ( \ |
1173 | - DBUS_INTERFACE_UPSTART \ |
1174 | - ".Error.UnknownJob", \ |
1175 | - _("Unknown job: %s"), \ |
1176 | - job_name); \ |
1177 | - return -1; \ |
1178 | - } \ |
1179 | - \ |
1180 | - job = job_find (session, class, NULL, instance); \ |
1181 | - if (job == NULL) { \ |
1182 | - nih_dbus_error_raise_printf ( \ |
1183 | - DBUS_INTERFACE_UPSTART \ |
1184 | - ".Error.UnknownJobInstance", \ |
1185 | - _("Unknown instance: %s of job %s"), \ |
1186 | - instance, job_name); \ |
1187 | - return -1; \ |
1188 | - } \ |
1189 | - } \ |
1190 | +#define control_get_job(session, job, job_name, instance) \ |
1191 | +{ \ |
1192 | + if (job_name != NULL ) { \ |
1193 | + JobClass *class; \ |
1194 | + \ |
1195 | + class = job_class_get_registered (job_name, session); \ |
1196 | + if (! class) { \ |
1197 | + nih_dbus_error_raise_printf ( \ |
1198 | + DBUS_INTERFACE_UPSTART \ |
1199 | + ".Error.UnknownJob", \ |
1200 | + _("Unknown job: %s"), \ |
1201 | + job_name); \ |
1202 | + return -1; \ |
1203 | + } \ |
1204 | + \ |
1205 | + job = job_find (session, class, NULL, instance); \ |
1206 | + if (job == NULL) { \ |
1207 | + nih_dbus_error_raise_printf ( \ |
1208 | + DBUS_INTERFACE_UPSTART \ |
1209 | + ".Error.UnknownJobInstance", \ |
1210 | + _("Unknown instance: %s of job %s"), \ |
1211 | + instance, job_name); \ |
1212 | + return -1; \ |
1213 | + } \ |
1214 | + } \ |
1215 | } |
1216 | |
1217 | NIH_BEGIN_EXTERN |
1218 | |
1219 | === modified file 'init/event.c' |
1220 | --- init/event.c 2012-12-14 23:47:51 +0000 |
1221 | +++ init/event.c 2013-06-05 16:21:24 +0000 |
1222 | @@ -315,8 +315,8 @@ |
1223 | |
1224 | /* We stop first so that if an event is listed both as a |
1225 | * stop and start event, it causes an active running process |
1226 | - * to be killed, the stop script then the start script to be |
1227 | - * run. In any other state, it has no special effect. |
1228 | + * to be killed, and then stop script then the start script |
1229 | + * to be run. In any other state, it has no special effect. |
1230 | * |
1231 | * (The other way around would be just strange, it'd cause |
1232 | * a process's start and stop scripts to be run without the |
1233 | @@ -638,7 +638,7 @@ |
1234 | json_object *json_env; |
1235 | Event *event = NULL; |
1236 | nih_local char *name = NULL; |
1237 | - char **env = NULL; |
1238 | + nih_local char **env = NULL; |
1239 | int session_index = -1; |
1240 | |
1241 | nih_assert (json); |
1242 | @@ -675,9 +675,19 @@ |
1243 | "progress", event->progress)) |
1244 | goto error; |
1245 | |
1246 | - if (! state_set_json_int_var_from_obj (json, event, failed)) |
1247 | + if (! state_get_json_int_var_to_obj (json, event, failed)) |
1248 | goto error; |
1249 | |
1250 | + /* We can only set the blockers count in the scenario that |
1251 | + * EventOperators are serialised (since without this, it is not |
1252 | + * possible to manually reconstruct the state of the |
1253 | + * EventOperators post-re-exec. |
1254 | + */ |
1255 | + if (json_object_object_get (json, "blockers")) { |
1256 | + if (! state_get_json_int_var_to_obj (json, event, blockers)) |
1257 | + goto error; |
1258 | + } |
1259 | + |
1260 | return event; |
1261 | |
1262 | error: |
1263 | |
1264 | === modified file 'init/event_operator.c' |
1265 | --- init/event_operator.c 2013-02-15 14:07:05 +0000 |
1266 | +++ init/event_operator.c 2013-06-05 16:21:24 +0000 |
1267 | @@ -59,7 +59,7 @@ |
1268 | * array of environment variables in KEY=VALUE form. @env will be referenced |
1269 | * by the new event. After calling this function, you should never use |
1270 | * nih_free() to free @env and instead use nih_unref() or nih_discard() if |
1271 | - * you longer need to use it. |
1272 | + * you no longer need to use it. |
1273 | * |
1274 | * If @parent is not NULL, it should be a pointer to another object which |
1275 | * will be used as a parent for the returned operator. When all parents |
1276 | @@ -782,8 +782,7 @@ |
1277 | env ? env : "")); |
1278 | nih_list_add_after (stack, &expr->entry); |
1279 | break; |
1280 | - } |
1281 | - else { |
1282 | + } else { |
1283 | /* We build the expression from visiting the logical |
1284 | * operators (and their children) only. |
1285 | */ |
1286 | @@ -864,3 +863,312 @@ |
1287 | |
1288 | return NIH_MUST (nih_strdup (NULL, latest->str)); |
1289 | } |
1290 | + |
1291 | +/** |
1292 | + * event_operator_type_enum_to_str: |
1293 | + * |
1294 | + * @type: EventOperatorType. |
1295 | + * |
1296 | + * Convert EventOperatorType to a string representation. |
1297 | + * |
1298 | + * Returns: string representation of @type, or NULL if not known. |
1299 | + **/ |
1300 | +const char * |
1301 | +event_operator_type_enum_to_str (EventOperatorType type) |
1302 | +{ |
1303 | + state_enum_to_str (EVENT_OR, type); |
1304 | + state_enum_to_str (EVENT_AND, type); |
1305 | + state_enum_to_str (EVENT_MATCH, type); |
1306 | + |
1307 | + return NULL; |
1308 | +} |
1309 | + |
1310 | +/** |
1311 | + * event_operator_type_str_to_enum: |
1312 | + * |
1313 | + * @type: string EventOperatorType value. |
1314 | + * |
1315 | + * Convert @expect back into an enum value. |
1316 | + * |
1317 | + * Returns: EventOperatorType representing @type, or -1 if not known. |
1318 | + **/ |
1319 | +EventOperatorType |
1320 | +event_operator_type_str_to_enum (const char *type) |
1321 | +{ |
1322 | + nih_assert (type); |
1323 | + |
1324 | + state_str_to_enum (EVENT_OR, type); |
1325 | + state_str_to_enum (EVENT_AND, type); |
1326 | + state_str_to_enum (EVENT_MATCH, type); |
1327 | + |
1328 | + return -1; |
1329 | +} |
1330 | + |
1331 | +/** |
1332 | + * event_operator_serialise: |
1333 | + * @oper: EventOperator to serialise. |
1334 | + * |
1335 | + * Convert @oper into a JSON representation for serialisation. |
1336 | + * Caller must free returned value using json_object_put(). |
1337 | + * |
1338 | + * Returns: JSON-serialised EventOperator object, or NULL on error. |
1339 | + **/ |
1340 | +json_object * |
1341 | +event_operator_serialise (const EventOperator *oper) |
1342 | +{ |
1343 | + json_object *json; |
1344 | + int event_index; |
1345 | + |
1346 | + nih_assert (oper); |
1347 | + |
1348 | + json = json_object_new_object (); |
1349 | + if (! json) |
1350 | + return NULL; |
1351 | + |
1352 | + if (! state_set_json_enum_var (json, |
1353 | + event_operator_type_enum_to_str, |
1354 | + "type", oper->type)) |
1355 | + goto error; |
1356 | + |
1357 | + if (! state_set_json_int_var_from_obj (json, oper, value)) |
1358 | + goto error; |
1359 | + |
1360 | + if (oper->name) { |
1361 | + if (! state_set_json_string_var_from_obj (json, oper, name)) |
1362 | + goto error; |
1363 | + } |
1364 | + |
1365 | + if (oper->env) { |
1366 | + if (! state_set_json_str_array_from_obj (json, oper, env)) |
1367 | + goto error; |
1368 | + } |
1369 | + |
1370 | + if (oper->event) { |
1371 | + event_index = event_to_index (oper->event); |
1372 | + if (event_index < 0) |
1373 | + goto error; |
1374 | + |
1375 | + if (! state_set_json_int_var (json, "event", event_index)) |
1376 | + goto error; |
1377 | + } |
1378 | + |
1379 | + return json; |
1380 | + |
1381 | +error: |
1382 | + json_object_put (json); |
1383 | + return NULL; |
1384 | + |
1385 | +} |
1386 | + |
1387 | +/** |
1388 | + * event_operator_serialise_all: |
1389 | + * |
1390 | + * @root: operator tree to serialise, |
1391 | + * |
1392 | + * Convert EventOperator tree to JSON representation. |
1393 | + * |
1394 | + * Returns: JSON object containing array of EventOperator nodes in post-order, |
1395 | + * or NULL on error. |
1396 | + */ |
1397 | +json_object * |
1398 | +event_operator_serialise_all (EventOperator *root) |
1399 | +{ |
1400 | + json_object *json; |
1401 | + json_object *json_node; |
1402 | + |
1403 | + nih_assert (root); |
1404 | + |
1405 | + json = json_object_new_array (); |
1406 | + if (! json) |
1407 | + return NULL; |
1408 | + |
1409 | + NIH_TREE_FOREACH_POST (&root->node, iter) { |
1410 | + EventOperator *oper = (EventOperator *)iter; |
1411 | + |
1412 | + json_node = event_operator_serialise (oper); |
1413 | + if (! json_node) |
1414 | + goto error; |
1415 | + |
1416 | + if (json_object_array_add (json, json_node) < 0) |
1417 | + goto error; |
1418 | + } |
1419 | + |
1420 | + return json; |
1421 | + |
1422 | +error: |
1423 | + json_object_put (json); |
1424 | + return NULL; |
1425 | +} |
1426 | + |
1427 | +/** |
1428 | + * event_operator_deserialise: |
1429 | + * @parent: parent, |
1430 | + * @json: JSON-serialised EventOperator object to deserialise. |
1431 | + * |
1432 | + * Create EventOperator from provided JSON. |
1433 | + * |
1434 | + * Returns: EventOperator object, or NULL on error. |
1435 | + **/ |
1436 | +EventOperator * |
1437 | +event_operator_deserialise (void *parent, json_object *json) |
1438 | +{ |
1439 | + EventOperator *oper = NULL; |
1440 | + EventOperatorType type = -1; |
1441 | + nih_local char *name = NULL; |
1442 | + nih_local char **env = NULL; |
1443 | + |
1444 | + nih_assert (json); |
1445 | + |
1446 | + if (! state_check_json_type (json, object)) |
1447 | + goto error; |
1448 | + |
1449 | + if (json_object_object_get (json, "name")) { |
1450 | + if (! state_get_json_string_var_strict (json, "name", NULL, name)) |
1451 | + goto error; |
1452 | + } |
1453 | + |
1454 | + if (! state_get_json_enum_var (json, |
1455 | + event_operator_type_str_to_enum, |
1456 | + "type", type)) |
1457 | + goto error; |
1458 | + |
1459 | + if (json_object_object_get (json, "env")) { |
1460 | + json_object *json_env; |
1461 | + if (! state_get_json_var_full (json, "env", array, json_env)) |
1462 | + goto error; |
1463 | + |
1464 | + /* XXX: note that we have to treat the environment array |
1465 | + * as a plain string array (rather than an environ |
1466 | + * array) at this point since the values are not |
1467 | + * expanded (do not necessarily contain '='), and hence |
1468 | + * would be discarded by the environ-handling routines. |
1469 | + */ |
1470 | + if (! state_deserialise_str_array (NULL, json_env, &env)) |
1471 | + goto error; |
1472 | + } |
1473 | + |
1474 | + oper = event_operator_new (parent, type, name, env); |
1475 | + if (! oper) |
1476 | + goto error; |
1477 | + |
1478 | + if (! state_get_json_int_var_to_obj (json, oper, value)) |
1479 | + goto error; |
1480 | + |
1481 | + if (json_object_object_get (json, "event")) { |
1482 | + int event_index; |
1483 | + |
1484 | + if (! state_get_json_int_var (json, "event", event_index)) |
1485 | + goto error; |
1486 | + |
1487 | + oper->event = event_from_index (event_index); |
1488 | + if (! oper->event) |
1489 | + goto error; |
1490 | + } |
1491 | + |
1492 | + return oper; |
1493 | + |
1494 | +error: |
1495 | + if (oper) |
1496 | + nih_free (oper); |
1497 | + |
1498 | + return NULL; |
1499 | +} |
1500 | + |
1501 | +/** |
1502 | + * event_operator_deserialise_all: |
1503 | + * |
1504 | + * @parent: parent, |
1505 | + * @json: root of JSON-serialised state. |
1506 | + * |
1507 | + * Convert EventOperator tree to JSON representation. |
1508 | + * |
1509 | + * Returns: EventOperator tree root node on success, or NULL on error. |
1510 | + */ |
1511 | +EventOperator * |
1512 | +event_operator_deserialise_all (void *parent, json_object *json) |
1513 | +{ |
1514 | + EventOperator *oper = NULL; |
1515 | + EventOperator *left_oper = NULL; |
1516 | + EventOperator *right_oper = NULL; |
1517 | + nih_local NihList *stack = NULL; |
1518 | + NihListEntry *item; |
1519 | + |
1520 | + nih_assert (json); |
1521 | + |
1522 | + stack = NIH_MUST (nih_list_new (NULL)); |
1523 | + |
1524 | + if (! state_check_json_type (json, array)) |
1525 | + goto error; |
1526 | + |
1527 | + for (int i = 0; i < json_object_array_length (json); i++) { |
1528 | + json_object *json_event_operator; |
1529 | + nih_local NihList *left = NULL; |
1530 | + nih_local NihList *right = NULL; |
1531 | + |
1532 | + json_event_operator = json_object_array_get_idx (json, i); |
1533 | + if (! json_event_operator) |
1534 | + goto error; |
1535 | + |
1536 | + if (! state_check_json_type (json_event_operator, object)) |
1537 | + goto error; |
1538 | + |
1539 | + oper = event_operator_deserialise (parent, json_event_operator); |
1540 | + if (! oper) |
1541 | + goto error; |
1542 | + |
1543 | + item = nih_list_entry_new (stack); |
1544 | + if (! item) |
1545 | + goto error; |
1546 | + |
1547 | + switch (oper->type) { |
1548 | + case EVENT_AND: |
1549 | + case EVENT_OR: |
1550 | + left = NIH_MUST (nih_list_new (NULL)); |
1551 | + right = NIH_MUST (nih_list_new (NULL)); |
1552 | + |
1553 | + /* pop the top two stack elements */ |
1554 | + nih_assert (! NIH_LIST_EMPTY (stack)); |
1555 | + right = nih_list_add (right, stack->next); |
1556 | + |
1557 | + nih_assert (! NIH_LIST_EMPTY (stack)); |
1558 | + left = nih_list_add (left, stack->next); |
1559 | + |
1560 | + left_oper = (EventOperator *)((NihListEntry *)left)->data; |
1561 | + right_oper = (EventOperator *)((NihListEntry *)right)->data; |
1562 | + |
1563 | + nih_assert (left_oper); |
1564 | + nih_assert (right_oper); |
1565 | + |
1566 | + /* Attach them as children of the new operator */ |
1567 | + nih_tree_add (&oper->node, &left_oper->node, NIH_TREE_LEFT); |
1568 | + nih_tree_add (&oper->node, &right_oper->node, NIH_TREE_RIGHT); |
1569 | + |
1570 | + /* FALL THROUGH: |
1571 | + * |
1572 | + * This will re-add the operator to the stack. |
1573 | + */ |
1574 | + |
1575 | + case EVENT_MATCH: |
1576 | + item->data = oper; |
1577 | + nih_list_add_after (stack, &item->entry); |
1578 | + break; |
1579 | + default: |
1580 | + nih_assert_not_reached (); |
1581 | + } |
1582 | + } |
1583 | + |
1584 | + nih_assert (! NIH_LIST_EMPTY (stack)); |
1585 | + |
1586 | + oper = ((NihListEntry *)stack->next)->data; |
1587 | + |
1588 | + nih_list_remove (stack->next); |
1589 | + nih_assert (NIH_LIST_EMPTY (stack)); |
1590 | + |
1591 | + return oper; |
1592 | + |
1593 | +error: |
1594 | + if (oper) |
1595 | + nih_free (oper); |
1596 | + |
1597 | + return NULL; |
1598 | +} |
1599 | |
1600 | === modified file 'init/event_operator.h' |
1601 | --- init/event_operator.h 2013-02-27 11:46:04 +0000 |
1602 | +++ init/event_operator.h 2013-06-05 16:21:24 +0000 |
1603 | @@ -108,8 +108,33 @@ |
1604 | |
1605 | void event_operator_reset (EventOperator *root); |
1606 | |
1607 | +const char * |
1608 | +event_operator_type_enum_to_str (EventOperatorType type) |
1609 | + __attribute__ ((warn_unused_result)); |
1610 | + |
1611 | +EventOperatorType |
1612 | +event_operator_type_str_to_enum (const char *type) |
1613 | + __attribute__ ((warn_unused_result)); |
1614 | + |
1615 | +json_object * |
1616 | +event_operator_serialise (const EventOperator *oper) |
1617 | + __attribute__ ((warn_unused_result)); |
1618 | + |
1619 | +json_object * |
1620 | +event_operator_serialise_all (EventOperator *root) |
1621 | + __attribute__ ((warn_unused_result)); |
1622 | + |
1623 | +EventOperator * |
1624 | +event_operator_deserialise (void *parent, json_object *json) |
1625 | + __attribute__ ((warn_unused_result)); |
1626 | + |
1627 | +EventOperator * |
1628 | +event_operator_deserialise_all (void *parent, json_object *json) |
1629 | + __attribute__ ((warn_unused_result)); |
1630 | + |
1631 | + |
1632 | char *event_operator_collapse (EventOperator *condition) |
1633 | - __attribute__ ((warn_unused_result)); |
1634 | + __attribute__ ((warn_unused_result, unused)); |
1635 | |
1636 | NIH_END_EXTERN |
1637 | |
1638 | |
1639 | === modified file 'init/job.c' |
1640 | --- init/job.c 2013-05-27 14:29:22 +0000 |
1641 | +++ init/job.c 2013-06-05 16:21:24 +0000 |
1642 | @@ -570,6 +570,7 @@ |
1643 | job->path)); |
1644 | } |
1645 | |
1646 | + /* Destroy the instance */ |
1647 | nih_free (job); |
1648 | } |
1649 | |
1650 | @@ -1577,7 +1578,6 @@ |
1651 | json_object *json_pid; |
1652 | json_object *json_fds; |
1653 | json_object *json_logs; |
1654 | - nih_local char *stop_on = NULL; |
1655 | |
1656 | nih_assert (job); |
1657 | |
1658 | @@ -1611,12 +1611,13 @@ |
1659 | goto error; |
1660 | |
1661 | if (job->stop_on) { |
1662 | - stop_on = event_operator_collapse (job->stop_on); |
1663 | - if (! stop_on) |
1664 | - goto error; |
1665 | - |
1666 | - if (! state_set_json_string_var (json, "stop_on", stop_on)) |
1667 | - goto error; |
1668 | + json_object *json_stop_on; |
1669 | + |
1670 | + json_stop_on = event_operator_serialise_all (job->stop_on); |
1671 | + if (! json_stop_on) |
1672 | + goto error; |
1673 | + |
1674 | + json_object_object_add (json, "stop_on", json_stop_on); |
1675 | } |
1676 | |
1677 | json_fds = state_serialise_int_array (int, job->fds, job->num_fds); |
1678 | @@ -1739,7 +1740,6 @@ |
1679 | json_object * |
1680 | job_serialise_all (const NihHash *jobs) |
1681 | { |
1682 | - int count = 0; |
1683 | json_object *json; |
1684 | |
1685 | nih_assert (jobs); |
1686 | @@ -1752,7 +1752,6 @@ |
1687 | json_object *json_job; |
1688 | Job *job = (Job *)iter; |
1689 | |
1690 | - count++; |
1691 | json_job = job_serialise (job); |
1692 | |
1693 | if (! json_job) |
1694 | @@ -1761,12 +1760,6 @@ |
1695 | json_object_array_add (json, json_job); |
1696 | } |
1697 | |
1698 | - /* Raise an error to avoid serialising job classes with |
1699 | - * no associated jobs. |
1700 | - */ |
1701 | - if (! count) |
1702 | - goto error; |
1703 | - |
1704 | return json; |
1705 | |
1706 | error: |
1707 | @@ -1794,6 +1787,7 @@ |
1708 | json_object *json_fds; |
1709 | json_object *json_pid; |
1710 | json_object *json_logs; |
1711 | + json_object *json_stop_on = NULL; |
1712 | size_t len; |
1713 | int ret; |
1714 | |
1715 | @@ -1833,37 +1827,53 @@ |
1716 | if (! state_get_json_env_array_to_obj (json, job, stop_env)) |
1717 | goto error; |
1718 | |
1719 | - if (json_object_object_get (json, "stop_on")) { |
1720 | - nih_local char *stop_on = NULL; |
1721 | - |
1722 | - if (! state_get_json_string_var_strict (json, "stop_on", NULL, stop_on)) |
1723 | - goto error; |
1724 | - |
1725 | - if (*stop_on) { |
1726 | - nih_local JobClass *tmp = NULL; |
1727 | - |
1728 | - tmp = NIH_MUST (job_class_new (NULL, "tmp", NULL)); |
1729 | - |
1730 | - tmp->stop_on = parse_on_simple (tmp, "stop", stop_on); |
1731 | - if (! tmp->stop_on) { |
1732 | - NihError *err; |
1733 | - |
1734 | - err = nih_error_get (); |
1735 | - |
1736 | - nih_error ("%s %s: %s", |
1737 | - _("BUG"), |
1738 | - _("instance 'stop on' parse error"), |
1739 | - err->message); |
1740 | - |
1741 | - nih_free (err); |
1742 | - |
1743 | - goto error; |
1744 | - } |
1745 | - |
1746 | - nih_free (job->stop_on); |
1747 | - job->stop_on = event_operator_copy (job, tmp->stop_on); |
1748 | + if (json_object_object_get_ex (json, "stop_on", &json_stop_on)) { |
1749 | + |
1750 | + if (state_check_json_type (json_stop_on, array)) { |
1751 | + |
1752 | + job->stop_on = event_operator_deserialise_all (job, json_stop_on); |
1753 | if (! job->stop_on) |
1754 | goto error; |
1755 | + } else { |
1756 | + nih_local char *stop_on = NULL; |
1757 | + |
1758 | + /* Old format (string) |
1759 | + * |
1760 | + * Note that we re-search for the JSON key here |
1761 | + * (json, rather than json_stop_on) to allow |
1762 | + * the use of the convenience macro. This is |
1763 | + * of course slower, but its a legacy scenario. |
1764 | + */ |
1765 | + |
1766 | + if (! state_get_json_string_var_strict (json, "stop_on", NULL, stop_on)) |
1767 | + goto error; |
1768 | + |
1769 | + if (*stop_on) { |
1770 | + nih_local JobClass *tmp = NULL; |
1771 | + |
1772 | + tmp = NIH_MUST (job_class_new (NULL, "tmp", NULL)); |
1773 | + |
1774 | + tmp->stop_on = parse_on_simple (tmp, "stop", stop_on); |
1775 | + if (! tmp->stop_on) { |
1776 | + NihError *err; |
1777 | + |
1778 | + err = nih_error_get (); |
1779 | + |
1780 | + nih_error ("%s %s: %s", |
1781 | + _("BUG"), |
1782 | + _("instance 'stop on' parse error"), |
1783 | + err->message); |
1784 | + |
1785 | + nih_free (err); |
1786 | + |
1787 | + goto error; |
1788 | + } |
1789 | + |
1790 | + nih_free (job->stop_on); |
1791 | + job->stop_on = event_operator_copy (job, tmp->stop_on); |
1792 | + if (! job->stop_on) |
1793 | + goto error; |
1794 | + } |
1795 | } |
1796 | } |
1797 | |
1798 | @@ -2284,7 +2294,7 @@ |
1799 | Job * |
1800 | job_find (const Session *session, |
1801 | JobClass *class, |
1802 | - char *job_class, |
1803 | + const char *job_class, |
1804 | const char *job_name) |
1805 | { |
1806 | Job *job; |
1807 | @@ -2293,7 +2303,7 @@ |
1808 | nih_assert (job_classes); |
1809 | |
1810 | if (! class) |
1811 | - class = job_class_find (session, job_class); |
1812 | + class = job_class_get_registered (job_class, session); |
1813 | |
1814 | if (! class) |
1815 | goto error; |
1816 | |
1817 | === modified file 'init/job.h' |
1818 | --- init/job.h 2013-05-15 13:21:54 +0000 |
1819 | +++ init/job.h 2013-06-05 16:21:24 +0000 |
1820 | @@ -222,8 +222,8 @@ |
1821 | |
1822 | Job * job_find (const Session *session, |
1823 | JobClass *class, |
1824 | - char *job_class, |
1825 | - const char *job_name) |
1826 | + const char *job_class, |
1827 | + const char *job_name) |
1828 | __attribute__ ((warn_unused_result)); |
1829 | |
1830 | NIH_END_EXTERN |
1831 | |
1832 | === modified file 'init/job_class.c' |
1833 | --- init/job_class.c 2013-05-15 13:21:54 +0000 |
1834 | +++ init/job_class.c 2013-06-05 16:21:24 +0000 |
1835 | @@ -2,7 +2,7 @@ |
1836 | * |
1837 | * job_class.c - job class definition handling |
1838 | * |
1839 | - * Copyright © 2011 Canonical Ltd. |
1840 | + * Copyright 2011 Canonical Ltd. |
1841 | * Author: Scott James Remnant <scott@netsplit.com>. |
1842 | * |
1843 | * This program is free software; you can redistribute it and/or modify |
1844 | @@ -371,6 +371,35 @@ |
1845 | return NULL; |
1846 | } |
1847 | |
1848 | +/** |
1849 | + * job_class_get_registered: |
1850 | + * |
1851 | + * @name: name of JobClass to search for, |
1852 | + * @session: Session of @class. |
1853 | + * |
1854 | + * Determine the currently registered JobClass with name @name for |
1855 | + * session @session. |
1856 | + * |
1857 | + * Returns: JobClass or NULL if no JobClass with name @name and |
1858 | + * session @session is registered. |
1859 | + **/ |
1860 | +JobClass * |
1861 | +job_class_get_registered (const char *name, const Session *session) |
1862 | +{ |
1863 | + JobClass *registered = NULL; |
1864 | + |
1865 | + nih_assert (name); |
1866 | + |
1867 | + job_class_init (); |
1868 | + |
1869 | + /* If we found an entry, ensure we only consider the appropriate session */ |
1870 | + do { |
1871 | + registered = (JobClass *)nih_hash_search (job_classes, |
1872 | + name, registered ? ®istered->entry : NULL); |
1873 | + } while (registered && registered->session != session); |
1874 | + |
1875 | + return registered; |
1876 | +} |
1877 | |
1878 | /** |
1879 | * job_class_consider: |
1880 | @@ -385,7 +414,8 @@ |
1881 | int |
1882 | job_class_consider (JobClass *class) |
1883 | { |
1884 | - JobClass *registered = NULL, *best = NULL; |
1885 | + JobClass *registered = NULL; |
1886 | + JobClass *best = NULL; |
1887 | |
1888 | nih_assert (class != NULL); |
1889 | |
1890 | @@ -395,16 +425,19 @@ |
1891 | nih_assert (best != NULL); |
1892 | nih_assert (best->session == class->session); |
1893 | |
1894 | - registered = (JobClass *)nih_hash_search (job_classes, class->name, NULL); |
1895 | - |
1896 | - /* If we found an entry, ensure we only consider the appropriate session */ |
1897 | - while (registered && registered->session != class->session) |
1898 | - registered = (JobClass *)nih_hash_search (job_classes, class->name, ®istered->entry); |
1899 | + registered = job_class_get_registered (class->name, class->session); |
1900 | |
1901 | if (registered != best) { |
1902 | - if (registered) |
1903 | - if (! job_class_remove (registered, class->session)) |
1904 | + if (registered) { |
1905 | + job_class_event_block (NULL, registered, best); |
1906 | + |
1907 | + if (! job_class_remove (registered, class->session)) { |
1908 | + /* Couldn't deregister, so undo */ |
1909 | + if (best->start_on) |
1910 | + event_operator_reset (best->start_on); |
1911 | return FALSE; |
1912 | + } |
1913 | + } |
1914 | |
1915 | job_class_add (best); |
1916 | } |
1917 | @@ -428,7 +461,8 @@ |
1918 | int |
1919 | job_class_reconsider (JobClass *class) |
1920 | { |
1921 | - JobClass *registered = NULL, *best = NULL; |
1922 | + JobClass *registered = NULL; |
1923 | + JobClass *best = NULL; |
1924 | |
1925 | nih_assert (class != NULL); |
1926 | |
1927 | @@ -436,11 +470,7 @@ |
1928 | |
1929 | best = conf_select_job (class->name, class->session); |
1930 | |
1931 | - registered = (JobClass *)nih_hash_search (job_classes, class->name, NULL); |
1932 | - |
1933 | - /* If we found an entry, ensure we only consider the appropriate session */ |
1934 | - while (registered && registered->session != class->session) |
1935 | - registered = (JobClass *)nih_hash_search (job_classes, class->name, ®istered->entry); |
1936 | + registered = job_class_get_registered (class->name, class->session); |
1937 | |
1938 | if (registered == class) { |
1939 | if (class != best) { |
1940 | @@ -459,6 +489,80 @@ |
1941 | } |
1942 | |
1943 | /** |
1944 | + * job_class_event_block: |
1945 | + * |
1946 | + * @parent: parent object for list, |
1947 | + * @old: original JobClass currently registered in job_classes, |
1948 | + * @new: new "best" JobClass that is not yet present in job_classes. |
1949 | + * |
1950 | + * Compare @old and @new start on EventOperator trees looking for |
1951 | + * matching events that occur in both (_and_ which implicitly still exist |
1952 | + * in the global events list). Events that satisfy these criteria will have |
1953 | + * their reference count elevated to allow @new to replace @old in job_classes |
1954 | + * without the destruction of @old freeing the events in question. |
1955 | + * |
1956 | + * Note that the reference count never needs to be decremented back |
1957 | + * again since this function effectively passes "ownership" of the event |
1958 | + * block from @old to @new, since @old will be replaced by @new but @new |
1959 | + * should replicate the EventOperator state of @old. |
1960 | + **/ |
1961 | +void |
1962 | +job_class_event_block (void *parent, JobClass *old, JobClass *new) |
1963 | +{ |
1964 | + EventOperator *old_root; |
1965 | + EventOperator *new_root; |
1966 | + |
1967 | + if (! old || ! new) |
1968 | + return; |
1969 | + |
1970 | + old_root = old->start_on; |
1971 | + new_root = new->start_on; |
1972 | + |
1973 | + /* If either @old or @new are NULL, or have no start_on |
1974 | + * condition, there is no need to modify any events. |
1975 | + */ |
1976 | + if (! old_root || ! new_root) |
1977 | + return; |
1978 | + |
1979 | + /* The old JobClass has associated instances meaning it |
1980 | + * will not be possible for job_class_remove() to replace it, so |
1981 | + * we don't need to manipulate any event reference counts. |
1982 | + */ |
1983 | + NIH_HASH_FOREACH (old->instances, iter) |
1984 | + return; |
1985 | + |
1986 | + NIH_TREE_FOREACH_POST (&old_root->node, iter) { |
1987 | + EventOperator *old_oper = (EventOperator *)iter; |
1988 | + Event *event; |
1989 | + |
1990 | + if (old_oper->type != EVENT_MATCH) |
1991 | + continue; |
1992 | + |
1993 | + /* Ignore nodes that are not blocking events */ |
1994 | + if (! old_oper->event) |
1995 | + continue; |
1996 | + |
1997 | + /* Since the JobClass is blocking an event, |
1998 | + * that event must be valid. |
1999 | + */ |
2000 | + event = old_oper->event; |
2001 | + |
2002 | + NIH_TREE_FOREACH_POST (&new_root->node, niter) { |
2003 | + EventOperator *new_oper = (EventOperator *)niter; |
2004 | + |
2005 | + if (new_oper->type != EVENT_MATCH) |
2006 | + continue; |
2007 | + |
2008 | + /* ignore the return - we just want to ensure |
2009 | + * that any events in @new that match those in |
2010 | + * @old have identical nodes. |
2011 | + */ |
2012 | + (void)event_operator_handle (new_oper, event, NULL); |
2013 | + } |
2014 | + } |
2015 | +} |
2016 | + |
2017 | +/** |
2018 | * job_class_add: |
2019 | * @class: new class to select. |
2020 | * |
2021 | @@ -493,24 +597,21 @@ |
2022 | void |
2023 | job_class_add_safe (JobClass *class) |
2024 | { |
2025 | - JobClass *existing = NULL; |
2026 | + JobClass *registered = NULL; |
2027 | |
2028 | nih_assert (class); |
2029 | nih_assert (class->name); |
2030 | |
2031 | control_init (); |
2032 | |
2033 | - /* Ensure no existing class exists for the same session */ |
2034 | - do { |
2035 | - existing = (JobClass *)nih_hash_search (job_classes, |
2036 | - class->name, existing ? &existing->entry : NULL); |
2037 | - } while (existing && existing->session != class->session); |
2038 | + registered = job_class_get_registered (class->name, class->session); |
2039 | |
2040 | - nih_assert (! existing); |
2041 | + nih_assert (! registered); |
2042 | |
2043 | job_class_add (class); |
2044 | } |
2045 | |
2046 | + |
2047 | /** |
2048 | * job_class_remove: |
2049 | * @class: class to remove, |
2050 | @@ -1286,6 +1387,8 @@ |
2051 | |
2052 | nih_assert (name); |
2053 | |
2054 | + job_class_init (); |
2055 | + |
2056 | do { |
2057 | class = (JobClass *)nih_hash_search (job_classes, name, prev); |
2058 | if (! class) |
2059 | @@ -1710,8 +1813,8 @@ |
2060 | json_object *json_normalexit; |
2061 | json_object *json_limits; |
2062 | json_object *json_jobs; |
2063 | - nih_local char *start_on = NULL; |
2064 | - nih_local char *stop_on = NULL; |
2065 | + json_object *json_start_on; |
2066 | + json_object *json_stop_on; |
2067 | int session_index; |
2068 | |
2069 | nih_assert (class); |
2070 | @@ -1721,15 +1824,6 @@ |
2071 | if (! json) |
2072 | return NULL; |
2073 | |
2074 | - /* XXX: chroot jobs are not currently supported |
2075 | - * due to ConfSources not currently being serialised. |
2076 | - */ |
2077 | - if (class->session) { |
2078 | - nih_info ("WARNING: serialisation of chroot " |
2079 | - "sessions not currently supported"); |
2080 | - goto error; |
2081 | - } |
2082 | - |
2083 | session_index = session_get_index (class->session); |
2084 | if (session_index < 0) |
2085 | goto error; |
2086 | @@ -1774,21 +1868,19 @@ |
2087 | json_object_object_add (json, "export", json_export); |
2088 | |
2089 | if (class->start_on) { |
2090 | - start_on = event_operator_collapse (class->start_on); |
2091 | - if (! start_on) |
2092 | + json_start_on = event_operator_serialise_all (class->start_on); |
2093 | + if (! json_start_on) |
2094 | goto error; |
2095 | |
2096 | - if (! state_set_json_string_var (json, "start_on", start_on)) |
2097 | - goto error; |
2098 | + json_object_object_add (json, "start_on", json_start_on); |
2099 | } |
2100 | |
2101 | if (class->stop_on) { |
2102 | - stop_on = event_operator_collapse (class->stop_on); |
2103 | - if (! stop_on) |
2104 | + json_stop_on = event_operator_serialise_all (class->stop_on); |
2105 | + if (! json_stop_on) |
2106 | goto error; |
2107 | |
2108 | - if (! state_set_json_string_var (json, "stop_on", stop_on)) |
2109 | - goto error; |
2110 | + json_object_object_add (json, "stop_on", json_stop_on); |
2111 | } |
2112 | |
2113 | json_emits = class->emits |
2114 | @@ -1888,7 +1980,20 @@ |
2115 | /** |
2116 | * job_class_serialise_all: |
2117 | * |
2118 | - * Convert existing JobClass objects to JSON representation. |
2119 | + * Convert existing JobClass objects in job classes hash to JSON |
2120 | + * representation. |
2121 | + * |
2122 | + * NOTE: despite its name, this function does not _necessarily_ |
2123 | + * serialise all JobClasses - there may be "best" (ie newer) JobClasses |
2124 | + * associated with ConfFiles that have not yet replaced the existing |
2125 | + * entries in the job classes hash if the JobClass has running instances. |
2126 | + * |
2127 | + * However, this is academic since although such data is not serialised, |
2128 | + * after the re-exec conf_reload() is called to recreate these "best" |
2129 | + * JobClasses. This also has the nice side-effect of ensuring that |
2130 | + * should jobs get created in the window when Upstart is statefully |
2131 | + * re-exec'ing, it will always see the newest versions of on-disk files |
2132 | + * (which is what the user expects). |
2133 | * |
2134 | * Returns: JSON object containing array of JobClass objects, |
2135 | * or NULL on error. |
2136 | @@ -1910,17 +2015,17 @@ |
2137 | |
2138 | json_class = job_class_serialise (class); |
2139 | |
2140 | - /* No object returned means the class doesn't need to be |
2141 | - * serialised. Even if this is a real failure, it's always |
2142 | - * better to serialise as much of the state as possible. |
2143 | - */ |
2144 | if (! json_class) |
2145 | - continue; |
2146 | + goto error; |
2147 | |
2148 | json_object_array_add (json, json_class); |
2149 | } |
2150 | |
2151 | return json; |
2152 | + |
2153 | +error: |
2154 | + json_object_put (json); |
2155 | + return NULL; |
2156 | } |
2157 | |
2158 | /** |
2159 | @@ -1937,11 +2042,14 @@ |
2160 | { |
2161 | json_object *json_normalexit; |
2162 | JobClass *class = NULL; |
2163 | + ConfFile *file = NULL; |
2164 | Session *session; |
2165 | int session_index = -1; |
2166 | int ret; |
2167 | nih_local char *name = NULL; |
2168 | nih_local char *path = NULL; |
2169 | + json_object *json_start_on = NULL; |
2170 | + json_object *json_stop_on = NULL; |
2171 | |
2172 | nih_assert (json); |
2173 | nih_assert (job_classes); |
2174 | @@ -1957,11 +2065,9 @@ |
2175 | |
2176 | session = session_from_index (session_index); |
2177 | |
2178 | - /* XXX: chroot jobs are not currently supported |
2179 | - * due to ConfSources not currently being serialised. |
2180 | - */ |
2181 | + /* XXX: chroot and old user session jobs not currently supported */ |
2182 | if (session) { |
2183 | - nih_info ("WARNING: deserialisation of chroot " |
2184 | + nih_info ("WARNING: deserialisation of user/chroot " |
2185 | "sessions not currently supported"); |
2186 | goto error; |
2187 | } |
2188 | @@ -1969,10 +2075,20 @@ |
2189 | if (! state_get_json_string_var_strict (json, "name", NULL, name)) |
2190 | goto error; |
2191 | |
2192 | + /* Create the class and associate it with the ConfFile */ |
2193 | class = job_class_new (NULL, name, session); |
2194 | if (! class) |
2195 | goto error; |
2196 | |
2197 | + /* Lookup the ConfFile associated with this class. |
2198 | + * |
2199 | + * Don't error if this fails since previous serialisation data |
2200 | + * formats did not encode ConfSources and ConfFiles. |
2201 | + */ |
2202 | + file = conf_file_find (name, session); |
2203 | + if (file) |
2204 | + file->job = class; |
2205 | + |
2206 | /* job_class_new() sets path */ |
2207 | if (! state_get_json_string_var_strict (json, "path", NULL, path)) |
2208 | goto error; |
2209 | @@ -2003,52 +2119,77 @@ |
2210 | goto error; |
2211 | |
2212 | /* start and stop conditions are optional */ |
2213 | - if (json_object_object_get (json, "start_on")) { |
2214 | - nih_local char *start_on = NULL; |
2215 | - |
2216 | - if (! state_get_json_string_var_strict (json, "start_on", NULL, start_on)) |
2217 | - goto error; |
2218 | - |
2219 | - if (*start_on) { |
2220 | - class->start_on = parse_on_simple (class, "start", start_on); |
2221 | - if (! class->start_on) { |
2222 | - NihError *err; |
2223 | - |
2224 | - err = nih_error_get (); |
2225 | - |
2226 | - nih_error ("%s %s: %s", |
2227 | - _("BUG"), |
2228 | - _("'start on' parse error"), |
2229 | - err->message); |
2230 | - |
2231 | - nih_free (err); |
2232 | - |
2233 | - goto error; |
2234 | + if (json_object_object_get_ex (json, "start_on", &json_start_on)) { |
2235 | + |
2236 | + if (state_check_json_type (json_start_on, array)) { |
2237 | + |
2238 | + class->start_on = event_operator_deserialise_all (class, json_start_on); |
2239 | + if (! class->start_on) |
2240 | + goto error; |
2241 | + } else { |
2242 | + nih_local char *start_on = NULL; |
2243 | + |
2244 | + /* Old format (string). |
2245 | + * |
2246 | + * Note that we re-search for the JSON key here |
2247 | + * (json, rather than json_start_on) to allow |
2248 | + * the use of the convenience macro. This is |
2249 | + * of course slower, but its a legacy scenario. |
2250 | + */ |
2251 | + if (! state_get_json_string_var_strict (json, "start_on", NULL, start_on)) |
2252 | + goto error; |
2253 | + |
2254 | + if (*start_on) { |
2255 | + class->start_on = parse_on_simple (class, "start", start_on); |
2256 | + if (! class->start_on) { |
2257 | + NihError *err; |
2258 | + |
2259 | + err = nih_error_get (); |
2260 | + |
2261 | + nih_error ("%s %s: %s", |
2262 | + _("BUG"), |
2263 | + _("'start on' parse error"), |
2264 | + err->message); |
2265 | + |
2266 | + nih_free (err); |
2267 | + |
2268 | + goto error; |
2269 | + } |
2270 | } |
2271 | } |
2272 | } |
2273 | |
2274 | - if (json_object_object_get (json, "stop_on")) { |
2275 | - nih_local char *stop_on = NULL; |
2276 | - |
2277 | - if (! state_get_json_string_var_strict (json, "stop_on", NULL, stop_on)) |
2278 | - goto error; |
2279 | - |
2280 | - if (*stop_on) { |
2281 | - class->stop_on = parse_on_simple (class, "stop", stop_on); |
2282 | - if (! class->stop_on) { |
2283 | - NihError *err; |
2284 | - |
2285 | - err = nih_error_get (); |
2286 | - |
2287 | - nih_error ("%s %s: %s", |
2288 | - _("BUG"), |
2289 | - _("'stop on' parse error"), |
2290 | - err->message); |
2291 | - |
2292 | - nih_free (err); |
2293 | - |
2294 | - goto error; |
2295 | + if (json_object_object_get_ex (json, "stop_on", &json_stop_on)) { |
2296 | + |
2297 | + if (state_check_json_type (json_stop_on, array)) { |
2298 | + |
2299 | + class->stop_on = event_operator_deserialise_all (class, json_stop_on); |
2300 | + if (! class->stop_on) |
2301 | + goto error; |
2302 | + } else { |
2303 | + nih_local char *stop_on = NULL; |
2304 | + |
2305 | + /* Old format (string) - re-search as above */ |
2306 | + |
2307 | + if (! state_get_json_string_var_strict (json, "stop_on", NULL, stop_on)) |
2308 | + goto error; |
2309 | + |
2310 | + if (*stop_on) { |
2311 | + class->stop_on = parse_on_simple (class, "stop", stop_on); |
2312 | + if (! class->stop_on) { |
2313 | + NihError *err; |
2314 | + |
2315 | + err = nih_error_get (); |
2316 | + |
2317 | + nih_error ("%s %s: %s", |
2318 | + _("BUG"), |
2319 | + _("'stop on' parse error"), |
2320 | + err->message); |
2321 | + |
2322 | + nih_free (err); |
2323 | + |
2324 | + goto error; |
2325 | + } |
2326 | } |
2327 | } |
2328 | } |
2329 | @@ -2137,12 +2278,17 @@ |
2330 | if (process_deserialise_all (json, class->process, class->process) < 0) |
2331 | goto error; |
2332 | |
2333 | - /* Force class to be known. |
2334 | - * |
2335 | - * We cannot use job_class_*consider() since the |
2336 | - * JobClasses have no associated ConfFile. |
2337 | - */ |
2338 | - job_class_add_safe (class); |
2339 | + if (file) { |
2340 | + /* Add the class to the job_classes hash if ConfFiles were |
2341 | + * available in the serialisation data. |
2342 | + */ |
2343 | + job_class_consider (class); |
2344 | + } else { |
2345 | + /* No ConfSources and ConfFiles were available in the |
2346 | + * serialisation data, so special-case the insertion. |
2347 | + */ |
2348 | + job_class_add_safe (class); |
2349 | + } |
2350 | |
2351 | /* Any jobs must be added after the class is registered |
2352 | * (since you cannot add a job to a partially-created |
2353 | @@ -2187,7 +2333,7 @@ |
2354 | goto error; |
2355 | |
2356 | for (int i = 0; i < json_object_array_length (json_classes); i++) { |
2357 | - json_object *json_class; |
2358 | + json_object *json_class; |
2359 | |
2360 | json_class = json_object_array_get_idx (json_classes, i); |
2361 | if (! json_class) |
2362 | @@ -2198,11 +2344,23 @@ |
2363 | |
2364 | class = job_class_deserialise (json_class); |
2365 | |
2366 | - /* For parity with the serialisation code, don't treat |
2367 | - * errors as fatal for the entire deserialisation. |
2368 | + /* Either memory is low or -- more likely -- a JobClass |
2369 | + * with a session was encountered, so keep going. |
2370 | */ |
2371 | - if (! class) |
2372 | - continue; |
2373 | + if (! class) { |
2374 | + int session_index = -1; |
2375 | + |
2376 | + if (state_get_json_int_var (json_class, "session", session_index) |
2377 | + && session_index > 0) { |
2378 | + /* Although ConfSources are now serialised, ignore |
2379 | + * JobClasses with associated user/chroot sessions to avoid |
2380 | + * behavioural changes for the time being. |
2381 | + */ |
2382 | + continue; |
2383 | + } else { |
2384 | + goto error; |
2385 | + } |
2386 | + } |
2387 | } |
2388 | |
2389 | return 0; |
2390 | @@ -2358,33 +2516,6 @@ |
2391 | } |
2392 | |
2393 | /** |
2394 | - * job_class_find: |
2395 | - * |
2396 | - * @session: session, |
2397 | - * @name: name of JobClass. |
2398 | - * |
2399 | - * Lookup a JobClass by session and name. |
2400 | - * |
2401 | - * Returns: JobClass associated with @session, or NULL if not found. |
2402 | - */ |
2403 | -JobClass * |
2404 | -job_class_find (const Session *session, |
2405 | - const char *name) |
2406 | -{ |
2407 | - JobClass *class = NULL; |
2408 | - |
2409 | - nih_assert (name); |
2410 | - nih_assert (job_classes); |
2411 | - |
2412 | - do { |
2413 | - class = (JobClass *)nih_hash_search (job_classes, |
2414 | - name, class ? &class->entry : NULL); |
2415 | - } while (class && class->session != session); |
2416 | - |
2417 | - return class; |
2418 | -} |
2419 | - |
2420 | -/** |
2421 | * job_class_max_kill_timeout: |
2422 | * |
2423 | * Determine maximum kill timeout for all running jobs. |
2424 | @@ -2413,3 +2544,29 @@ |
2425 | |
2426 | return kill_timeout; |
2427 | } |
2428 | + |
2429 | +/** |
2430 | + * job_class_get_index: |
2431 | + * @class: JobClass to search for. |
2432 | + * |
2433 | + * Returns: index of @class in the job classes hash, |
2434 | + * or -1 if not found. |
2435 | + **/ |
2436 | +ssize_t |
2437 | +job_class_get_index (const JobClass *class) |
2438 | +{ |
2439 | + ssize_t i = 0; |
2440 | + |
2441 | + nih_assert (class); |
2442 | + |
2443 | + NIH_HASH_FOREACH (job_classes, iter) { |
2444 | + JobClass *c = (JobClass *)iter; |
2445 | + |
2446 | + if (! strcmp (c->name, class->name) |
2447 | + && c->session == class->session) |
2448 | + return i; |
2449 | + i++; |
2450 | + } |
2451 | + |
2452 | + return -1; |
2453 | +} |
2454 | |
2455 | === modified file 'init/job_class.h' |
2456 | --- init/job_class.h 2013-05-15 13:21:54 +0000 |
2457 | +++ init/job_class.h 2013-06-05 16:21:24 +0000 |
2458 | @@ -359,12 +359,18 @@ |
2459 | |
2460 | void job_class_prepare_reexec (void); |
2461 | |
2462 | -JobClass * job_class_find (const Session *session, const char *name) |
2463 | - __attribute__ ((warn_unused_result)); |
2464 | - |
2465 | time_t job_class_max_kill_timeout (void) |
2466 | __attribute__ ((warn_unused_result)); |
2467 | |
2468 | +JobClass *job_class_get_registered (const char *name, const Session *session) |
2469 | + __attribute__ ((warn_unused_result)); |
2470 | + |
2471 | +void job_class_event_block (void *parent, JobClass *old, JobClass *new); |
2472 | + |
2473 | +ssize_t |
2474 | +job_class_get_index (const JobClass *class) |
2475 | + __attribute__ ((warn_unused_result)); |
2476 | + |
2477 | NIH_END_EXTERN |
2478 | |
2479 | #endif /* INIT_JOB_CLASS_H */ |
2480 | |
2481 | === modified file 'init/main.c' |
2482 | --- init/main.c 2013-04-22 10:30:09 +0000 |
2483 | +++ init/main.c 2013-06-05 16:21:24 +0000 |
2484 | @@ -126,6 +126,7 @@ |
2485 | extern int disable_job_logging; |
2486 | extern int use_session_bus; |
2487 | extern int default_console; |
2488 | +extern int write_state_file; |
2489 | extern char *log_dir; |
2490 | |
2491 | |
2492 | @@ -173,6 +174,9 @@ |
2493 | { 0, "user", N_("start in user mode (as used for user sessions)"), |
2494 | NULL, NULL, &user_mode, NULL }, |
2495 | |
2496 | + { 0, "write-state-file", N_("attempt to write state file on every re-exec"), |
2497 | + NULL, NULL, &write_state_file, NULL }, |
2498 | + |
2499 | /* Ignore invalid options */ |
2500 | { '-', "--", NULL, NULL, NULL, NULL, NULL }, |
2501 | |
2502 | |
2503 | === modified file 'init/paths.h' |
2504 | --- init/paths.h 2013-01-25 10:08:19 +0000 |
2505 | +++ init/paths.h 2013-06-05 16:21:24 +0000 |
2506 | @@ -97,6 +97,15 @@ |
2507 | #endif |
2508 | |
2509 | /** |
2510 | + * STATE_FILE_ENV: |
2511 | + * |
2512 | + * If set, write STATE_FILE on any re-exec. |
2513 | + **/ |
2514 | +#ifndef STATE_FILE_ENV |
2515 | +#define STATE_FILE_ENV "UPSTART_WRITE_STATEFILE" |
2516 | +#endif |
2517 | + |
2518 | +/** |
2519 | * INIT_XDG_SUBDIR: |
2520 | * |
2521 | * This is the name of the sub folder we will use when constructing |
2522 | |
2523 | === modified file 'init/state.c' |
2524 | --- init/state.c 2013-02-28 16:40:36 +0000 |
2525 | +++ init/state.c 2013-06-05 16:21:24 +0000 |
2526 | @@ -47,6 +47,7 @@ |
2527 | json_object *json_sessions = NULL; |
2528 | json_object *json_events = NULL; |
2529 | json_object *json_classes = NULL; |
2530 | +json_object *json_conf_sources = NULL; |
2531 | |
2532 | extern char *log_dir; |
2533 | |
2534 | @@ -67,6 +68,13 @@ |
2535 | **/ |
2536 | int restart = FALSE; |
2537 | |
2538 | +/** |
2539 | + * write_state_file: |
2540 | + * |
2541 | + * If TRUE, write STATE_FILE on every re-exec. |
2542 | + **/ |
2543 | +int write_state_file = FALSE; |
2544 | + |
2545 | /* Prototypes for static functions */ |
2546 | static JobClass * |
2547 | state_index_to_job_class (int job_class_index) |
2548 | @@ -233,6 +241,9 @@ |
2549 | if (state_from_string (buffer->buf) < 0) |
2550 | goto error; |
2551 | |
2552 | + if (write_state_file || getenv (STATE_FILE_ENV)) |
2553 | + state_write_file (buffer); |
2554 | + |
2555 | return 0; |
2556 | |
2557 | error: |
2558 | @@ -327,8 +338,8 @@ |
2559 | int |
2560 | state_to_string (char **json_string, size_t *len) |
2561 | { |
2562 | - json_object *json; |
2563 | - const char *value; |
2564 | + json_object *json; |
2565 | + const char *value; |
2566 | |
2567 | nih_assert (json_string); |
2568 | nih_assert (len); |
2569 | @@ -339,24 +350,39 @@ |
2570 | return -1; |
2571 | |
2572 | json_sessions = session_serialise_all (); |
2573 | - if (! json_sessions) |
2574 | + if (! json_sessions) { |
2575 | + nih_error ("%s Sessions", _("Failed to serialise")); |
2576 | goto error; |
2577 | + } |
2578 | |
2579 | json_object_object_add (json, "sessions", json_sessions); |
2580 | |
2581 | json_events = event_serialise_all (); |
2582 | - if (! json_events) |
2583 | + if (! json_events) { |
2584 | + nih_error ("%s Events", _("Failed to serialise")); |
2585 | goto error; |
2586 | + } |
2587 | |
2588 | json_object_object_add (json, "events", json_events); |
2589 | |
2590 | json_classes = job_class_serialise_all (); |
2591 | |
2592 | - if (! json_classes) |
2593 | + if (! json_classes) { |
2594 | + nih_error ("%s JobClasses", _("Failed to serialise")); |
2595 | goto error; |
2596 | + } |
2597 | |
2598 | json_object_object_add (json, "job_classes", json_classes); |
2599 | |
2600 | + json_conf_sources = conf_source_serialise_all (); |
2601 | + |
2602 | + if (! json_conf_sources) { |
2603 | + nih_error ("%s ConfSources", _("Failed to serialise")); |
2604 | + goto error; |
2605 | + } |
2606 | + |
2607 | + json_object_object_add (json, "conf_sources", json_conf_sources); |
2608 | + |
2609 | /* Note that the returned value is managed by json-c! */ |
2610 | value = json_object_to_json_string (json); |
2611 | if (! value) |
2612 | @@ -410,17 +436,37 @@ |
2613 | if (! state_check_json_type (json, object)) |
2614 | goto out; |
2615 | |
2616 | - if (session_deserialise_all (json) < 0) |
2617 | - goto out; |
2618 | - |
2619 | - if (event_deserialise_all (json) < 0) |
2620 | - goto out; |
2621 | - |
2622 | - if (job_class_deserialise_all (json) < 0) |
2623 | - goto out; |
2624 | - |
2625 | - if (state_deserialise_resolve_deps (json) < 0) |
2626 | - goto out; |
2627 | + if (session_deserialise_all (json) < 0) { |
2628 | + nih_error ("%s Sessions", _("Failed to deserialise")); |
2629 | + goto out; |
2630 | + } |
2631 | + |
2632 | + if (event_deserialise_all (json) < 0) { |
2633 | + nih_error ("%s Events", _("Failed to deserialise")); |
2634 | + goto out; |
2635 | + } |
2636 | + |
2637 | + /* Again, we cannot error here since older JSON state data did |
2638 | + * not encode ConfSource or ConfFile objects. |
2639 | + */ |
2640 | + if (json_object_object_get (json, "conf_sources")) { |
2641 | + if (conf_source_deserialise_all (json) < 0) { |
2642 | + nih_error ("%s ConfSources", _("Failed to deserialise")); |
2643 | + goto out; |
2644 | + } |
2645 | + } else { |
2646 | + nih_warn ("%s", _("No ConfSources present in state data")); |
2647 | + } |
2648 | + |
2649 | + if (job_class_deserialise_all (json) < 0) { |
2650 | + nih_error ("%s JobClasses", _("Failed to deserialise")); |
2651 | + goto out; |
2652 | + } |
2653 | + |
2654 | + if (state_deserialise_resolve_deps (json) < 0) { |
2655 | + nih_error (_("Failed to resolve deserialisation dependencies")); |
2656 | + goto out; |
2657 | + } |
2658 | |
2659 | ret = 0; |
2660 | |
2661 | @@ -1118,7 +1164,6 @@ |
2662 | return json_type_null; |
2663 | } |
2664 | |
2665 | - |
2666 | /** |
2667 | * state_deserialise_resolve_deps: |
2668 | * |
2669 | @@ -1135,8 +1180,9 @@ |
2670 | { |
2671 | nih_assert (json); |
2672 | |
2673 | - /* XXX: Events, JobClasses, Jobs and DBusConnections must have |
2674 | - * previously been deserialised before invoking this function. |
2675 | + /* XXX: Sessions, Events, JobClasses, Jobs and DBusConnections |
2676 | + * must have previously been deserialised before invoking |
2677 | + * this function. |
2678 | */ |
2679 | nih_assert (json_sessions); |
2680 | nih_assert (json_events); |
2681 | @@ -1175,14 +1221,21 @@ |
2682 | |
2683 | /* lookup class associated with JSON class index */ |
2684 | class = state_index_to_job_class (i); |
2685 | - if (! class) |
2686 | - goto error; |
2687 | - |
2688 | - /* XXX: user and chroot jobs are not currently supported |
2689 | - * due to ConfSources not currently being serialised. |
2690 | - */ |
2691 | - if (class->session) |
2692 | - continue; |
2693 | + if (! class) { |
2694 | + int session_index = -1; |
2695 | + |
2696 | + if (state_get_json_int_var (json_class, "session", session_index) |
2697 | + && session_index > 0) { |
2698 | + |
2699 | + /* Although ConfSources are now serialised, ignore |
2700 | + * JobClasses with associated user/chroot sessions to avoid |
2701 | + * behavioural changes for the time being. |
2702 | + */ |
2703 | + continue; |
2704 | + } else { |
2705 | + goto error; |
2706 | + } |
2707 | + } |
2708 | |
2709 | if (! state_get_json_var_full (json_class, "jobs", array, json_jobs)) |
2710 | goto error; |
2711 | @@ -1526,7 +1579,12 @@ |
2712 | |
2713 | blocked = NIH_MUST (blocked_new (parent, BLOCKED_EVENT, event)); |
2714 | nih_list_add (list, &blocked->entry); |
2715 | - event_block (blocked->event); |
2716 | + |
2717 | + /* Event must already exist and should have |
2718 | + * blockers associated for it to have a blocked |
2719 | + * object pointing at it. |
2720 | + */ |
2721 | + nih_assert (blocked->event->blockers); |
2722 | } |
2723 | break; |
2724 | |
2725 | @@ -1655,7 +1713,6 @@ |
2726 | if (! json_blocked) |
2727 | goto error; |
2728 | |
2729 | - |
2730 | /* Don't error in this scenario to allow for possibility |
2731 | * that version of Upstart that performed the |
2732 | * serialisation did not correctly handle user and |
2733 | @@ -1894,7 +1951,7 @@ |
2734 | void |
2735 | stateful_reexec (void) |
2736 | { |
2737 | - int fds[2] = { -1 }; |
2738 | + int fds[2] = { -1, -1 }; |
2739 | pid_t pid; |
2740 | sigset_t mask, oldmask; |
2741 | nih_local char *state_data = NULL; |
2742 | |
2743 | === modified file 'init/state.h' |
2744 | --- init/state.h 2013-02-27 11:46:04 +0000 |
2745 | +++ init/state.h 2013-06-05 16:21:24 +0000 |
2746 | @@ -4,7 +4,7 @@ |
2747 | * |
2748 | * - XXX: Deferred work: |
2749 | * - handling of Upstart-in-initramfs - for this to work, it would be |
2750 | - * necessary to serialise ConfSources along with the following: |
2751 | + * necessary to serialise ConfSources (done) along with the following: |
2752 | * |
2753 | * (1) inode number of source->path |
2754 | * (2) inode number of '/' |
2755 | @@ -27,12 +27,6 @@ |
2756 | * Note too that (2)+(3) are the only reliable method for Upstart to |
2757 | * detect that is *has* changed filesystem context. |
2758 | * |
2759 | - * - Since ConfSources are NOT serialised, it is currently not possible |
2760 | - * to support chroot jobs (because the only ConfSource |
2761 | - * objects created are those at startup (for '/etc/init/'): any |
2762 | - * pre-existing ConfSources with non-NULL Session objects will |
2763 | - * be ignored). |
2764 | - * |
2765 | * - parent/child timeout handling: we won't support down-grading initially. |
2766 | * |
2767 | * - dbus-connections: only be re-exec'ing post-boot so bridges won't |
2768 | @@ -371,7 +365,7 @@ |
2769 | * |
2770 | * Name of file that is written below the job log directory if the |
2771 | * newly re-exec'ed init instance failed to understand the JSON sent to |
2772 | - * it by the old instance. |
2773 | + * it by the old instance (or if requested by STATE_FILE_ENV). |
2774 | * |
2775 | * This could happen for example if the old instance generated invalid |
2776 | * JSON, or JSON in an unexected format. |
2777 | @@ -1226,6 +1220,9 @@ |
2778 | struct rlimit *state_rlimit_deserialise (json_object *json) |
2779 | __attribute__ ((warn_unused_result)); |
2780 | |
2781 | +int state_get_version (void) |
2782 | + __attribute__ ((warn_unused_result)); |
2783 | + |
2784 | extern char **args_copy; |
2785 | extern int restart; |
2786 | |
2787 | |
2788 | === added file 'init/tests/data/upstart-1.8+apparmor.json' |
2789 | --- init/tests/data/upstart-1.8+apparmor.json 1970-01-01 00:00:00 +0000 |
2790 | +++ init/tests/data/upstart-1.8+apparmor.json 2013-06-05 16:21:24 +0000 |
2791 | @@ -0,0 +1,7962 @@ |
2792 | +{ |
2793 | + "sessions" : [], |
2794 | + "job_classes" : [ |
2795 | + { |
2796 | + "setuid" : null, |
2797 | + "jobs" : [ |
2798 | + { |
2799 | + "trace_state" : "TRACE_NONE", |
2800 | + "failed" : 0, |
2801 | + "state" : "JOB_RUNNING", |
2802 | + "failed_process" : "PROCESS_INVALID", |
2803 | + "pid" : [ |
2804 | + 669, |
2805 | + 0, |
2806 | + 0, |
2807 | + 0, |
2808 | + 0, |
2809 | + 0 |
2810 | + ], |
2811 | + "start_env" : [], |
2812 | + "trace_forks" : 2, |
2813 | + "respawn_time" : 0, |
2814 | + "log" : [ |
2815 | + { |
2816 | + "path" : null |
2817 | + }, |
2818 | + { |
2819 | + "path" : null |
2820 | + }, |
2821 | + { |
2822 | + "path" : null |
2823 | + }, |
2824 | + { |
2825 | + "path" : null |
2826 | + }, |
2827 | + { |
2828 | + "path" : null |
2829 | + }, |
2830 | + { |
2831 | + "path" : null |
2832 | + } |
2833 | + ], |
2834 | + "respawn_count" : 0, |
2835 | + "kill_process" : "PROCESS_INVALID", |
2836 | + "stop_on" : "stopping dbus", |
2837 | + "env" : [ |
2838 | + "PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin", |
2839 | + "TERM=linux", |
2840 | + "JOB=dbus", |
2841 | + "INSTANCE=", |
2842 | + "UPSTART_EVENTS=filesystem started" |
2843 | + ], |
2844 | + "name" : "", |
2845 | + "path" : "/com/ubuntu/Upstart/jobs/avahi_2ddaemon/_", |
2846 | + "exit_status" : 0, |
2847 | + "goal" : "JOB_START", |
2848 | + "stop_env" : [], |
2849 | + "fds" : [] |
2850 | + } |
2851 | + ], |
2852 | + "emits" : [], |
2853 | + "session" : 0, |
2854 | + "debug" : 0, |
2855 | + "export" : [], |
2856 | + "expect" : "EXPECT_DAEMON", |
2857 | + "stop_on" : "stopping dbus", |
2858 | + "chroot" : null, |
2859 | + "console" : "CONSOLE_LOG", |
2860 | + "kill_signal" : 15, |
2861 | + "name" : "avahi-daemon", |
2862 | + "instance" : "", |
2863 | + "description" : "mDNS/DNS-SD daemon", |
2864 | + "respawn_interval" : 5, |
2865 | + "process" : [ |
2866 | + { |
2867 | + "script" : 1, |
2868 | + "command" : "opts=\"-D\"\n[ -e \"/etc/eucalyptus/avahi-daemon.conf\" ] && opts=\"${opts} -f /etc/eucalyptus/avahi-daemon.conf\"\nexec avahi-daemon ${opts}\n" |
2869 | + }, |
2870 | + { |
2871 | + "script" : 1, |
2872 | + "command" : "/lib/init/apparmor-profile-load usr.sbin.avahi-daemon\n" |
2873 | + }, |
2874 | + { |
2875 | + "script" : 0, |
2876 | + "command" : null |
2877 | + }, |
2878 | + { |
2879 | + "script" : 0, |
2880 | + "command" : null |
2881 | + }, |
2882 | + { |
2883 | + "script" : 0, |
2884 | + "command" : null |
2885 | + }, |
2886 | + { |
2887 | + "script" : 0, |
2888 | + "command" : null |
2889 | + } |
2890 | + ], |
2891 | + "apparmor_switch" : null, |
2892 | + "respawn_limit" : 10, |
2893 | + "author" : null, |
2894 | + "respawn" : 1, |
2895 | + "nice" : -21, |
2896 | + "limits" : [ |
2897 | + { |
2898 | + "rlim_cur" : 0, |
2899 | + "rlim_max" : 0 |
2900 | + }, |
2901 | + { |
2902 | + "rlim_cur" : 0, |
2903 | + "rlim_max" : 0 |
2904 | + }, |
2905 | + { |
2906 | + "rlim_cur" : 0, |
2907 | + "rlim_max" : 0 |
2908 | + }, |
2909 | + { |
2910 | + "rlim_cur" : 0, |
2911 | + "rlim_max" : 0 |
2912 | + }, |
2913 | + { |
2914 | + "rlim_cur" : 0, |
2915 | + "rlim_max" : 0 |
2916 | + }, |
2917 | + { |
2918 | + "rlim_cur" : 0, |
2919 | + "rlim_max" : 0 |
2920 | + }, |
2921 | + { |
2922 | + "rlim_cur" : 0, |
2923 | + "rlim_max" : 0 |
2924 | + }, |
2925 | + { |
2926 | + "rlim_cur" : 0, |
2927 | + "rlim_max" : 0 |
2928 | + }, |
2929 | + { |
2930 | + "rlim_cur" : 0, |
2931 | + "rlim_max" : 0 |
2932 | + }, |
2933 | + { |
2934 | + "rlim_cur" : 0, |
2935 | + "rlim_max" : 0 |
2936 | + }, |
2937 | + { |
2938 | + "rlim_cur" : 0, |
2939 | + "rlim_max" : 0 |
2940 | + }, |
2941 | + { |
2942 | + "rlim_cur" : 0, |
2943 | + "rlim_max" : 0 |
2944 | + }, |
2945 | + { |
2946 | + "rlim_cur" : 0, |
2947 | + "rlim_max" : 0 |
2948 | + }, |
2949 | + { |
2950 | + "rlim_cur" : 0, |
2951 | + "rlim_max" : 0 |
2952 | + }, |
2953 | + { |
2954 | + "rlim_cur" : 0, |
2955 | + "rlim_max" : 0 |
2956 | + }, |
2957 | + { |
2958 | + "rlim_cur" : 0, |
2959 | + "rlim_max" : 0 |
2960 | + } |
2961 | + ], |
2962 | + "oom_score_adj" : 0, |
2963 | + "normalexit" : [], |
2964 | + "kill_timeout" : 5, |
2965 | + "usage" : null, |
2966 | + "env" : [], |
2967 | + "version" : null, |
2968 | + "task" : 0, |
2969 | + "path" : "/com/ubuntu/Upstart/jobs/avahi_2ddaemon", |
2970 | + "deleted" : 0, |
2971 | + "chdir" : null, |
2972 | + "start_on" : "(filesystem and started dbus)", |
2973 | + "umask" : 18, |
2974 | + "setgid" : null |
2975 | + }, |
2976 | + { |
2977 | + "setuid" : null, |
2978 | + "jobs" : [ |
2979 | + { |
2980 | + "trace_state" : "TRACE_NONE", |
2981 | + "failed" : 0, |
2982 | + "state" : "JOB_RUNNING", |
2983 | + "failed_process" : "PROCESS_INVALID", |
2984 | + "pid" : [ |
2985 | + 0, |
2986 | + 0, |
2987 | + 0, |
2988 | + 0, |
2989 | + 0, |
2990 | + 0 |
2991 | + ], |
2992 | + "start_env" : [], |
2993 | + "trace_forks" : 0, |
2994 | + "respawn_time" : 0, |
2995 | + "log" : [ |
2996 | + { |
2997 | + "path" : null |
2998 | + }, |
2999 | + { |
3000 | + "path" : null |
3001 | + }, |
3002 | + { |
3003 | + "path" : null |
3004 | + }, |
3005 | + { |
3006 | + "path" : null |
3007 | + }, |
3008 | + { |
3009 | + "path" : null |
3010 | + }, |
3011 | + { |
3012 | + "path" : null |
3013 | + } |
3014 | + ], |
3015 | + "respawn_count" : 0, |
3016 | + "kill_process" : "PROCESS_INVALID", |
3017 | + "env" : [ |
3018 | + "PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin", |
3019 | + "TERM=linux", |
3020 | + "UPSTART_EVENTS=virtual-filesystems" |
3021 | + ], |
3022 | + "name" : "", |
3023 | + "path" : "/com/ubuntu/Upstart/jobs/mountnfs_2dbootclean_2esh/_", |
3024 | + "exit_status" : 0, |
3025 | + "goal" : "JOB_START", |
3026 | + "stop_env" : [], |
3027 | + "fds" : [] |
3028 | + } |
3029 | + ], |
3030 | + "emits" : [], |
3031 | + "session" : 0, |
3032 | + "debug" : 0, |
3033 | + "export" : [], |
3034 | + "expect" : "EXPECT_NONE", |
3035 | + "chroot" : null, |
3036 | + "console" : "CONSOLE_LOG", |
3037 | + "kill_signal" : 15, |
3038 | + "name" : "mountnfs-bootclean.sh", |
3039 | + "instance" : "", |
3040 | + "description" : null, |
3041 | + "respawn_interval" : 5, |
3042 | + "process" : [ |
3043 | + { |
3044 | + "script" : 0, |
3045 | + "command" : null |
3046 | + }, |
3047 | + { |
3048 | + "script" : 0, |
3049 | + "command" : null |
3050 | + }, |
3051 | + { |
3052 | + "script" : 0, |
3053 | + "command" : null |
3054 | + }, |
3055 | + { |
3056 | + "script" : 0, |
3057 | + "command" : null |
3058 | + }, |
3059 | + { |
3060 | + "script" : 0, |
3061 | + "command" : null |
3062 | + }, |
3063 | + { |
3064 | + "script" : 0, |
3065 | + "command" : null |
3066 | + } |
3067 | + ], |
3068 | + "apparmor_switch" : null, |
3069 | + "respawn_limit" : 10, |
3070 | + "author" : null, |
3071 | + "respawn" : 0, |
3072 | + "nice" : -21, |
3073 | + "limits" : [ |
3074 | + { |
3075 | + "rlim_cur" : 0, |
3076 | + "rlim_max" : 0 |
3077 | + }, |
3078 | + { |
3079 | + "rlim_cur" : 0, |
3080 | + "rlim_max" : 0 |
3081 | + }, |
3082 | + { |
3083 | + "rlim_cur" : 0, |
3084 | + "rlim_max" : 0 |
3085 | + }, |
3086 | + { |
3087 | + "rlim_cur" : 0, |
3088 | + "rlim_max" : 0 |
3089 | + }, |
3090 | + { |
3091 | + "rlim_cur" : 0, |
3092 | + "rlim_max" : 0 |
3093 | + }, |
3094 | + { |
3095 | + "rlim_cur" : 0, |
3096 | + "rlim_max" : 0 |
3097 | + }, |
3098 | + { |
3099 | + "rlim_cur" : 0, |
3100 | + "rlim_max" : 0 |
3101 | + }, |
3102 | + { |
3103 | + "rlim_cur" : 0, |
3104 | + "rlim_max" : 0 |
3105 | + }, |
3106 | + { |
3107 | + "rlim_cur" : 0, |
3108 | + "rlim_max" : 0 |
3109 | + }, |
3110 | + { |
3111 | + "rlim_cur" : 0, |
3112 | + "rlim_max" : 0 |
3113 | + }, |
3114 | + { |
3115 | + "rlim_cur" : 0, |
3116 | + "rlim_max" : 0 |
3117 | + }, |
3118 | + { |
3119 | + "rlim_cur" : 0, |
3120 | + "rlim_max" : 0 |
3121 | + }, |
3122 | + { |
3123 | + "rlim_cur" : 0, |
3124 | + "rlim_max" : 0 |
3125 | + }, |
3126 | + { |
3127 | + "rlim_cur" : 0, |
3128 | + "rlim_max" : 0 |
3129 | + }, |
3130 | + { |
3131 | + "rlim_cur" : 0, |
3132 | + "rlim_max" : 0 |
3133 | + }, |
3134 | + { |
3135 | + "rlim_cur" : 0, |
3136 | + "rlim_max" : 0 |
3137 | + } |
3138 | + ], |
3139 | + "oom_score_adj" : 0, |
3140 | + "normalexit" : [], |
3141 | + "kill_timeout" : 5, |
3142 | + "usage" : null, |
3143 | + "env" : [], |
3144 | + "version" : null, |
3145 | + "task" : 0, |
3146 | + "path" : "/com/ubuntu/Upstart/jobs/mountnfs_2dbootclean_2esh", |
3147 | + "deleted" : 0, |
3148 | + "chdir" : null, |
3149 | + "start_on" : "virtual-filesystems", |
3150 | + "umask" : 18, |
3151 | + "setgid" : null |
3152 | + }, |
3153 | + { |
3154 | + "setuid" : null, |
3155 | + "jobs" : [ |
3156 | + { |
3157 | + "trace_state" : "TRACE_NONE", |
3158 | + "failed" : 0, |
3159 | + "state" : "JOB_RUNNING", |
3160 | + "failed_process" : "PROCESS_INVALID", |
3161 | + "pid" : [ |
3162 | + 659, |
3163 | + 0, |
3164 | + 0, |
3165 | + 0, |
3166 | + 0, |
3167 | + 0 |
3168 | + ], |
3169 | + "start_env" : [], |
3170 | + "trace_forks" : 1, |
3171 | + "respawn_time" : 0, |
3172 | + "log" : [ |
3173 | + { |
3174 | + "path" : null |
3175 | + }, |
3176 | + { |
3177 | + "path" : null |
3178 | + }, |
3179 | + { |
3180 | + "path" : null |
3181 | + }, |
3182 | + { |
3183 | + "path" : null |
3184 | + }, |
3185 | + { |
3186 | + "path" : null |
3187 | + }, |
3188 | + { |
3189 | + "path" : null |
3190 | + } |
3191 | + ], |
3192 | + "respawn_count" : 0, |
3193 | + "kill_process" : "PROCESS_INVALID", |
3194 | + "stop_on" : "runlevel [06]", |
3195 | + "env" : [ |
3196 | + "PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin", |
3197 | + "TERM=linux", |
3198 | + "UPSTART_EVENTS=filesystem" |
3199 | + ], |
3200 | + "name" : "", |
3201 | + "path" : "/com/ubuntu/Upstart/jobs/rsyslog/_", |
3202 | + "exit_status" : 0, |
3203 | + "goal" : "JOB_START", |
3204 | + "stop_env" : [], |
3205 | + "fds" : [] |
3206 | + } |
3207 | + ], |
3208 | + "emits" : [], |
3209 | + "session" : 0, |
3210 | + "debug" : 0, |
3211 | + "export" : [], |
3212 | + "expect" : "EXPECT_FORK", |
3213 | + "stop_on" : "runlevel [06]", |
3214 | + "chroot" : null, |
3215 | + "console" : "CONSOLE_LOG", |
3216 | + "kill_signal" : 15, |
3217 | + "name" : "rsyslog", |
3218 | + "instance" : "", |
3219 | + "description" : "system logging daemon", |
3220 | + "respawn_interval" : 5, |
3221 | + "process" : [ |
3222 | + { |
3223 | + "script" : 1, |
3224 | + "command" : ". /etc/default/rsyslog\nexec rsyslogd $RSYSLOGD_OPTIONS\n" |
3225 | + }, |
3226 | + { |
3227 | + "script" : 1, |
3228 | + "command" : "/lib/init/apparmor-profile-load usr.sbin.rsyslogd\n" |
3229 | + }, |
3230 | + { |
3231 | + "script" : 0, |
3232 | + "command" : null |
3233 | + }, |
3234 | + { |
3235 | + "script" : 0, |
3236 | + "command" : null |
3237 | + }, |
3238 | + { |
3239 | + "script" : 0, |
3240 | + "command" : null |
3241 | + }, |
3242 | + { |
3243 | + "script" : 0, |
3244 | + "command" : null |
3245 | + } |
3246 | + ], |
3247 | + "apparmor_switch" : null, |
3248 | + "respawn_limit" : 10, |
3249 | + "author" : null, |
3250 | + "respawn" : 1, |
3251 | + "nice" : -21, |
3252 | + "limits" : [ |
3253 | + { |
3254 | + "rlim_cur" : 0, |
3255 | + "rlim_max" : 0 |
3256 | + }, |
3257 | + { |
3258 | + "rlim_cur" : 0, |
3259 | + "rlim_max" : 0 |
3260 | + }, |
3261 | + { |
3262 | + "rlim_cur" : 0, |
3263 | + "rlim_max" : 0 |
3264 | + }, |
3265 | + { |
3266 | + "rlim_cur" : 0, |
3267 | + "rlim_max" : 0 |
3268 | + }, |
3269 | + { |
3270 | + "rlim_cur" : 0, |
3271 | + "rlim_max" : 0 |
3272 | + }, |
3273 | + { |
3274 | + "rlim_cur" : 0, |
3275 | + "rlim_max" : 0 |
3276 | + }, |
3277 | + { |
3278 | + "rlim_cur" : 0, |
3279 | + "rlim_max" : 0 |
3280 | + }, |
3281 | + { |
3282 | + "rlim_cur" : 0, |
3283 | + "rlim_max" : 0 |
3284 | + }, |
3285 | + { |
3286 | + "rlim_cur" : 0, |
3287 | + "rlim_max" : 0 |
3288 | + }, |
3289 | + { |
3290 | + "rlim_cur" : 0, |
3291 | + "rlim_max" : 0 |
3292 | + }, |
3293 | + { |
3294 | + "rlim_cur" : 0, |
3295 | + "rlim_max" : 0 |
3296 | + }, |
3297 | + { |
3298 | + "rlim_cur" : 0, |
3299 | + "rlim_max" : 0 |
3300 | + }, |
3301 | + { |
3302 | + "rlim_cur" : 0, |
3303 | + "rlim_max" : 0 |
3304 | + }, |
3305 | + { |
3306 | + "rlim_cur" : 0, |
3307 | + "rlim_max" : 0 |
3308 | + }, |
3309 | + { |
3310 | + "rlim_cur" : 0, |
3311 | + "rlim_max" : 0 |
3312 | + }, |
3313 | + { |
3314 | + "rlim_cur" : 0, |
3315 | + "rlim_max" : 0 |
3316 | + } |
3317 | + ], |
3318 | + "oom_score_adj" : 0, |
3319 | + "normalexit" : [], |
3320 | + "kill_timeout" : 5, |
3321 | + "usage" : null, |
3322 | + "env" : [], |
3323 | + "version" : null, |
3324 | + "task" : 0, |
3325 | + "path" : "/com/ubuntu/Upstart/jobs/rsyslog", |
3326 | + "deleted" : 0, |
3327 | + "chdir" : null, |
3328 | + "start_on" : "filesystem", |
3329 | + "umask" : 18, |
3330 | + "setgid" : null |
3331 | + }, |
3332 | + { |
3333 | + "setuid" : null, |
3334 | + "jobs" : [ |
3335 | + { |
3336 | + "trace_state" : "TRACE_NONE", |
3337 | + "failed" : 0, |
3338 | + "state" : "JOB_RUNNING", |
3339 | + "failed_process" : "PROCESS_INVALID", |
3340 | + "pid" : [ |
3341 | + 1023, |
3342 | + 0, |
3343 | + 0, |
3344 | + 0, |
3345 | + 0, |
3346 | + 0 |
3347 | + ], |
3348 | + "start_env" : [], |
3349 | + "trace_forks" : 0, |
3350 | + "respawn_time" : 0, |
3351 | + "log" : [ |
3352 | + { |
3353 | + "path" : null |
3354 | + }, |
3355 | + { |
3356 | + "path" : null |
3357 | + }, |
3358 | + { |
3359 | + "path" : null |
3360 | + }, |
3361 | + { |
3362 | + "path" : null |
3363 | + }, |
3364 | + { |
3365 | + "path" : null |
3366 | + }, |
3367 | + { |
3368 | + "path" : null |
3369 | + } |
3370 | + ], |
3371 | + "respawn_count" : 0, |
3372 | + "kill_process" : "PROCESS_INVALID", |
3373 | + "stop_on" : "runlevel [!23]", |
3374 | + "env" : [ |
3375 | + "PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin", |
3376 | + "TERM=linux", |
3377 | + "RUNLEVEL=2", |
3378 | + "PREVLEVEL=N", |
3379 | + "UPSTART_EVENTS=runlevel not-container" |
3380 | + ], |
3381 | + "name" : "", |
3382 | + "path" : "/com/ubuntu/Upstart/jobs/tty4/_", |
3383 | + "exit_status" : 0, |
3384 | + "goal" : "JOB_START", |
3385 | + "stop_env" : [], |
3386 | + "fds" : [] |
3387 | + } |
3388 | + ], |
3389 | + "emits" : [], |
3390 | + "session" : 0, |
3391 | + "debug" : 0, |
3392 | + "export" : [], |
3393 | + "expect" : "EXPECT_NONE", |
3394 | + "stop_on" : "runlevel [!23]", |
3395 | + "chroot" : null, |
3396 | + "console" : "CONSOLE_LOG", |
3397 | + "kill_signal" : 15, |
3398 | + "name" : "tty4", |
3399 | + "instance" : "", |
3400 | + "description" : null, |
3401 | + "respawn_interval" : 5, |
3402 | + "process" : [ |
3403 | + { |
3404 | + "script" : 0, |
3405 | + "command" : "/sbin/getty -8 38400 tty4" |
3406 | + }, |
3407 | + { |
3408 | + "script" : 0, |
3409 | + "command" : null |
3410 | + }, |
3411 | + { |
3412 | + "script" : 0, |
3413 | + "command" : null |
3414 | + }, |
3415 | + { |
3416 | + "script" : 0, |
3417 | + "command" : null |
3418 | + }, |
3419 | + { |
3420 | + "script" : 0, |
3421 | + "command" : null |
3422 | + }, |
3423 | + { |
3424 | + "script" : 0, |
3425 | + "command" : null |
3426 | + } |
3427 | + ], |
3428 | + "apparmor_switch" : null, |
3429 | + "respawn_limit" : 10, |
3430 | + "author" : null, |
3431 | + "respawn" : 1, |
3432 | + "nice" : -21, |
3433 | + "limits" : [ |
3434 | + { |
3435 | + "rlim_cur" : 0, |
3436 | + "rlim_max" : 0 |
3437 | + }, |
3438 | + { |
3439 | + "rlim_cur" : 0, |
3440 | + "rlim_max" : 0 |
3441 | + }, |
3442 | + { |
3443 | + "rlim_cur" : 0, |
3444 | + "rlim_max" : 0 |
3445 | + }, |
3446 | + { |
3447 | + "rlim_cur" : 0, |
3448 | + "rlim_max" : 0 |
3449 | + }, |
3450 | + { |
3451 | + "rlim_cur" : 0, |
3452 | + "rlim_max" : 0 |
3453 | + }, |
3454 | + { |
3455 | + "rlim_cur" : 0, |
3456 | + "rlim_max" : 0 |
3457 | + }, |
3458 | + { |
3459 | + "rlim_cur" : 0, |
3460 | + "rlim_max" : 0 |
3461 | + }, |
3462 | + { |
3463 | + "rlim_cur" : 0, |
3464 | + "rlim_max" : 0 |
3465 | + }, |
3466 | + { |
3467 | + "rlim_cur" : 0, |
3468 | + "rlim_max" : 0 |
3469 | + }, |
3470 | + { |
3471 | + "rlim_cur" : 0, |
3472 | + "rlim_max" : 0 |
3473 | + }, |
3474 | + { |
3475 | + "rlim_cur" : 0, |
3476 | + "rlim_max" : 0 |
3477 | + }, |
3478 | + { |
3479 | + "rlim_cur" : 0, |
3480 | + "rlim_max" : 0 |
3481 | + }, |
3482 | + { |
3483 | + "rlim_cur" : 0, |
3484 | + "rlim_max" : 0 |
3485 | + }, |
3486 | + { |
3487 | + "rlim_cur" : 0, |
3488 | + "rlim_max" : 0 |
3489 | + }, |
3490 | + { |
3491 | + "rlim_cur" : 0, |
3492 | + "rlim_max" : 0 |
3493 | + }, |
3494 | + { |
3495 | + "rlim_cur" : 0, |
3496 | + "rlim_max" : 0 |
3497 | + } |
3498 | + ], |
3499 | + "oom_score_adj" : 0, |
3500 | + "normalexit" : [], |
3501 | + "kill_timeout" : 5, |
3502 | + "usage" : null, |
3503 | + "env" : [], |
3504 | + "version" : null, |
3505 | + "task" : 0, |
3506 | + "path" : "/com/ubuntu/Upstart/jobs/tty4", |
3507 | + "deleted" : 0, |
3508 | + "chdir" : null, |
3509 | + "start_on" : "(runlevel [23] and ((not-container or container CONTAINER=lxc) or container CONTAINER=lxc-libvirt))", |
3510 | + "umask" : 18, |
3511 | + "setgid" : null |
3512 | + }, |
3513 | + { |
3514 | + "setuid" : null, |
3515 | + "jobs" : [ |
3516 | + { |
3517 | + "trace_state" : "TRACE_NONE", |
3518 | + "failed" : 0, |
3519 | + "state" : "JOB_RUNNING", |
3520 | + "failed_process" : "PROCESS_INVALID", |
3521 | + "pid" : [ |
3522 | + 562, |
3523 | + 0, |
3524 | + 0, |
3525 | + 0, |
3526 | + 0, |
3527 | + 0 |
3528 | + ], |
3529 | + "start_env" : [], |
3530 | + "trace_forks" : 1, |
3531 | + "respawn_time" : 0, |
3532 | + "log" : [ |
3533 | + { |
3534 | + "path" : null |
3535 | + }, |
3536 | + { |
3537 | + "path" : null |
3538 | + }, |
3539 | + { |
3540 | + "path" : null |
3541 | + }, |
3542 | + { |
3543 | + "path" : null |
3544 | + }, |
3545 | + { |
3546 | + "path" : null |
3547 | + }, |
3548 | + { |
3549 | + "path" : null |
3550 | + } |
3551 | + ], |
3552 | + "respawn_count" : 0, |
3553 | + "kill_process" : "PROCESS_INVALID", |
3554 | + "stop_on" : "runlevel [06]", |
3555 | + "env" : [ |
3556 | + "PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin", |
3557 | + "TERM=linux", |
3558 | + "UPSTART_EVENTS=virtual-filesystems" |
3559 | + ], |
3560 | + "name" : "", |
3561 | + "path" : "/com/ubuntu/Upstart/jobs/udev/_", |
3562 | + "exit_status" : 0, |
3563 | + "goal" : "JOB_START", |
3564 | + "stop_env" : [], |
3565 | + "fds" : [] |
3566 | + } |
3567 | + ], |
3568 | + "emits" : [], |
3569 | + "session" : 0, |
3570 | + "debug" : 0, |
3571 | + "export" : [], |
3572 | + "expect" : "EXPECT_FORK", |
3573 | + "stop_on" : "runlevel [06]", |
3574 | + "chroot" : null, |
3575 | + "console" : "CONSOLE_LOG", |
3576 | + "kill_signal" : 15, |
3577 | + "name" : "udev", |
3578 | + "instance" : "", |
3579 | + "description" : "device node and kernel event manager", |
3580 | + "respawn_interval" : 5, |
3581 | + "process" : [ |
3582 | + { |
3583 | + "script" : 0, |
3584 | + "command" : "/lib/systemd/systemd-udevd --daemon" |
3585 | + }, |
3586 | + { |
3587 | + "script" : 0, |
3588 | + "command" : null |
3589 | + }, |
3590 | + { |
3591 | + "script" : 0, |
3592 | + "command" : null |
3593 | + }, |
3594 | + { |
3595 | + "script" : 0, |
3596 | + "command" : null |
3597 | + }, |
3598 | + { |
3599 | + "script" : 0, |
3600 | + "command" : null |
3601 | + }, |
3602 | + { |
3603 | + "script" : 0, |
3604 | + "command" : null |
3605 | + } |
3606 | + ], |
3607 | + "apparmor_switch" : null, |
3608 | + "respawn_limit" : 10, |
3609 | + "author" : null, |
3610 | + "respawn" : 1, |
3611 | + "nice" : -21, |
3612 | + "limits" : [ |
3613 | + { |
3614 | + "rlim_cur" : 0, |
3615 | + "rlim_max" : 0 |
3616 | + }, |
3617 | + { |
3618 | + "rlim_cur" : 0, |
3619 | + "rlim_max" : 0 |
3620 | + }, |
3621 | + { |
3622 | + "rlim_cur" : 0, |
3623 | + "rlim_max" : 0 |
3624 | + }, |
3625 | + { |
3626 | + "rlim_cur" : 0, |
3627 | + "rlim_max" : 0 |
3628 | + }, |
3629 | + { |
3630 | + "rlim_cur" : 0, |
3631 | + "rlim_max" : 0 |
3632 | + }, |
3633 | + { |
3634 | + "rlim_cur" : 0, |
3635 | + "rlim_max" : 0 |
3636 | + }, |
3637 | + { |
3638 | + "rlim_cur" : 0, |
3639 | + "rlim_max" : 0 |
3640 | + }, |
3641 | + { |
3642 | + "rlim_cur" : 0, |
3643 | + "rlim_max" : 0 |
3644 | + }, |
3645 | + { |
3646 | + "rlim_cur" : 0, |
3647 | + "rlim_max" : 0 |
3648 | + }, |
3649 | + { |
3650 | + "rlim_cur" : 0, |
3651 | + "rlim_max" : 0 |
3652 | + }, |
3653 | + { |
3654 | + "rlim_cur" : 0, |
3655 | + "rlim_max" : 0 |
3656 | + }, |
3657 | + { |
3658 | + "rlim_cur" : 0, |
3659 | + "rlim_max" : 0 |
3660 | + }, |
3661 | + { |
3662 | + "rlim_cur" : 0, |
3663 | + "rlim_max" : 0 |
3664 | + }, |
3665 | + { |
3666 | + "rlim_cur" : 0, |
3667 | + "rlim_max" : 0 |
3668 | + }, |
3669 | + { |
3670 | + "rlim_cur" : 0, |
3671 | + "rlim_max" : 0 |
3672 | + }, |
3673 | + { |
3674 | + "rlim_cur" : 0, |
3675 | + "rlim_max" : 0 |
3676 | + } |
3677 | + ], |
3678 | + "oom_score_adj" : 0, |
3679 | + "normalexit" : [], |
3680 | + "kill_timeout" : 5, |
3681 | + "usage" : null, |
3682 | + "env" : [], |
3683 | + "version" : null, |
3684 | + "task" : 0, |
3685 | + "path" : "/com/ubuntu/Upstart/jobs/udev", |
3686 | + "deleted" : 0, |
3687 | + "chdir" : null, |
3688 | + "start_on" : "virtual-filesystems", |
3689 | + "umask" : 18, |
3690 | + "setgid" : null |
3691 | + }, |
3692 | + { |
3693 | + "setuid" : null, |
3694 | + "jobs" : [ |
3695 | + { |
3696 | + "trace_state" : "TRACE_NONE", |
3697 | + "failed" : 0, |
3698 | + "state" : "JOB_RUNNING", |
3699 | + "failed_process" : "PROCESS_INVALID", |
3700 | + "pid" : [ |
3701 | + 545, |
3702 | + 0, |
3703 | + 0, |
3704 | + 0, |
3705 | + 0, |
3706 | + 0 |
3707 | + ], |
3708 | + "start_env" : [], |
3709 | + "trace_forks" : 2, |
3710 | + "respawn_time" : 0, |
3711 | + "log" : [ |
3712 | + { |
3713 | + "path" : null |
3714 | + }, |
3715 | + { |
3716 | + "path" : null |
3717 | + }, |
3718 | + { |
3719 | + "path" : null |
3720 | + }, |
3721 | + { |
3722 | + "path" : null |
3723 | + }, |
3724 | + { |
3725 | + "path" : null |
3726 | + }, |
3727 | + { |
3728 | + "path" : null |
3729 | + } |
3730 | + ], |
3731 | + "respawn_count" : 0, |
3732 | + "kill_process" : "PROCESS_INVALID", |
3733 | + "stop_on" : "stopped udev", |
3734 | + "env" : [ |
3735 | + "PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin", |
3736 | + "TERM=linux", |
3737 | + "JOB=udev", |
3738 | + "INSTANCE=", |
3739 | + "UPSTART_EVENTS=starting" |
3740 | + ], |
3741 | + "name" : "", |
3742 | + "path" : "/com/ubuntu/Upstart/jobs/upstart_2dudev_2dbridge/_", |
3743 | + "exit_status" : 0, |
3744 | + "goal" : "JOB_START", |
3745 | + "stop_env" : [], |
3746 | + "fds" : [] |
3747 | + } |
3748 | + ], |
3749 | + "emits" : [ |
3750 | + "*-device-added", |
3751 | + "*-device-removed", |
3752 | + "*-device-changed", |
3753 | + "*-device-online", |
3754 | + "*-device-offline" |
3755 | + ], |
3756 | + "session" : 0, |
3757 | + "debug" : 0, |
3758 | + "export" : [], |
3759 | + "expect" : "EXPECT_DAEMON", |
3760 | + "stop_on" : "stopped udev", |
3761 | + "chroot" : null, |
3762 | + "console" : "CONSOLE_LOG", |
3763 | + "kill_signal" : 15, |
3764 | + "name" : "upstart-udev-bridge", |
3765 | + "instance" : "", |
3766 | + "description" : "Bridge udev events into upstart", |
3767 | + "respawn_interval" : 5, |
3768 | + "process" : [ |
3769 | + { |
3770 | + "script" : 0, |
3771 | + "command" : "upstart-udev-bridge --daemon" |
3772 | + }, |
3773 | + { |
3774 | + "script" : 0, |
3775 | + "command" : null |
3776 | + }, |
3777 | + { |
3778 | + "script" : 0, |
3779 | + "command" : null |
3780 | + }, |
3781 | + { |
3782 | + "script" : 0, |
3783 | + "command" : null |
3784 | + }, |
3785 | + { |
3786 | + "script" : 0, |
3787 | + "command" : null |
3788 | + }, |
3789 | + { |
3790 | + "script" : 0, |
3791 | + "command" : null |
3792 | + } |
3793 | + ], |
3794 | + "apparmor_switch" : null, |
3795 | + "respawn_limit" : 10, |
3796 | + "author" : null, |
3797 | + "respawn" : 1, |
3798 | + "nice" : -21, |
3799 | + "limits" : [ |
3800 | + { |
3801 | + "rlim_cur" : 0, |
3802 | + "rlim_max" : 0 |
3803 | + }, |
3804 | + { |
3805 | + "rlim_cur" : 0, |
3806 | + "rlim_max" : 0 |
3807 | + }, |
3808 | + { |
3809 | + "rlim_cur" : 0, |
3810 | + "rlim_max" : 0 |
3811 | + }, |
3812 | + { |
3813 | + "rlim_cur" : 0, |
3814 | + "rlim_max" : 0 |
3815 | + }, |
3816 | + { |
3817 | + "rlim_cur" : 0, |
3818 | + "rlim_max" : 0 |
3819 | + }, |
3820 | + { |
3821 | + "rlim_cur" : 0, |
3822 | + "rlim_max" : 0 |
3823 | + }, |
3824 | + { |
3825 | + "rlim_cur" : 0, |
3826 | + "rlim_max" : 0 |
3827 | + }, |
3828 | + { |
3829 | + "rlim_cur" : 0, |
3830 | + "rlim_max" : 0 |
3831 | + }, |
3832 | + { |
3833 | + "rlim_cur" : 0, |
3834 | + "rlim_max" : 0 |
3835 | + }, |
3836 | + { |
3837 | + "rlim_cur" : 0, |
3838 | + "rlim_max" : 0 |
3839 | + }, |
3840 | + { |
3841 | + "rlim_cur" : 0, |
3842 | + "rlim_max" : 0 |
3843 | + }, |
3844 | + { |
3845 | + "rlim_cur" : 0, |
3846 | + "rlim_max" : 0 |
3847 | + }, |
3848 | + { |
3849 | + "rlim_cur" : 0, |
3850 | + "rlim_max" : 0 |
3851 | + }, |
3852 | + { |
3853 | + "rlim_cur" : 0, |
3854 | + "rlim_max" : 0 |
3855 | + }, |
3856 | + { |
3857 | + "rlim_cur" : 0, |
3858 | + "rlim_max" : 0 |
3859 | + }, |
3860 | + { |
3861 | + "rlim_cur" : 0, |
3862 | + "rlim_max" : 0 |
3863 | + } |
3864 | + ], |
3865 | + "oom_score_adj" : 0, |
3866 | + "normalexit" : [], |
3867 | + "kill_timeout" : 5, |
3868 | + "usage" : null, |
3869 | + "env" : [], |
3870 | + "version" : null, |
3871 | + "task" : 0, |
3872 | + "path" : "/com/ubuntu/Upstart/jobs/upstart_2dudev_2dbridge", |
3873 | + "deleted" : 0, |
3874 | + "chdir" : null, |
3875 | + "start_on" : "starting udev", |
3876 | + "umask" : 18, |
3877 | + "setgid" : null |
3878 | + }, |
3879 | + { |
3880 | + "setuid" : null, |
3881 | + "jobs" : [ |
3882 | + { |
3883 | + "trace_state" : "TRACE_NONE", |
3884 | + "failed" : 0, |
3885 | + "state" : "JOB_RUNNING", |
3886 | + "failed_process" : "PROCESS_INVALID", |
3887 | + "pid" : [ |
3888 | + 1143, |
3889 | + 0, |
3890 | + 0, |
3891 | + 0, |
3892 | + 0, |
3893 | + 0 |
3894 | + ], |
3895 | + "start_env" : [], |
3896 | + "trace_forks" : 1, |
3897 | + "respawn_time" : 0, |
3898 | + "log" : [ |
3899 | + { |
3900 | + "path" : null |
3901 | + }, |
3902 | + { |
3903 | + "path" : null |
3904 | + }, |
3905 | + { |
3906 | + "path" : null |
3907 | + }, |
3908 | + { |
3909 | + "path" : null |
3910 | + }, |
3911 | + { |
3912 | + "path" : null |
3913 | + }, |
3914 | + { |
3915 | + "path" : null |
3916 | + } |
3917 | + ], |
3918 | + "respawn_count" : 0, |
3919 | + "kill_process" : "PROCESS_INVALID", |
3920 | + "stop_on" : "runlevel [!2345]", |
3921 | + "env" : [ |
3922 | + "PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin", |
3923 | + "TERM=linux", |
3924 | + "CRASH_DB_URL=https://daisy.ubuntu.com", |
3925 | + "RUNLEVEL=2", |
3926 | + "PREVLEVEL=N", |
3927 | + "UPSTART_EVENTS=runlevel" |
3928 | + ], |
3929 | + "name" : "", |
3930 | + "path" : "/com/ubuntu/Upstart/jobs/whoopsie/_", |
3931 | + "exit_status" : 0, |
3932 | + "goal" : "JOB_START", |
3933 | + "stop_env" : [], |
3934 | + "fds" : [] |
3935 | + } |
3936 | + ], |
3937 | + "emits" : [], |
3938 | + "session" : 0, |
3939 | + "debug" : 0, |
3940 | + "export" : [], |
3941 | + "expect" : "EXPECT_FORK", |
3942 | + "stop_on" : "runlevel [!2345]", |
3943 | + "chroot" : null, |
3944 | + "console" : "CONSOLE_LOG", |
3945 | + "kill_signal" : 15, |
3946 | + "name" : "whoopsie", |
3947 | + "instance" : "", |
3948 | + "description" : "crash report submission daemon", |
3949 | + "respawn_interval" : 5, |
3950 | + "process" : [ |
3951 | + { |
3952 | + "script" : 0, |
3953 | + "command" : "whoopsie" |
3954 | + }, |
3955 | + { |
3956 | + "script" : 1, |
3957 | + "command" : " [ -x /usr/bin/ubiquity-dm ] && { stop; exit 0; }\n\n if ! grep report_crashes=true /etc/default/whoopsie -sqi; then\n stop; exit 0\n fi\n" |
3958 | + }, |
3959 | + { |
3960 | + "script" : 0, |
3961 | + "command" : null |
3962 | + }, |
3963 | + { |
3964 | + "script" : 0, |
3965 | + "command" : null |
3966 | + }, |
3967 | + { |
3968 | + "script" : 0, |
3969 | + "command" : null |
3970 | + }, |
3971 | + { |
3972 | + "script" : 0, |
3973 | + "command" : null |
3974 | + } |
3975 | + ], |
3976 | + "apparmor_switch" : null, |
3977 | + "respawn_limit" : 10, |
3978 | + "author" : null, |
3979 | + "respawn" : 1, |
3980 | + "nice" : -21, |
3981 | + "limits" : [ |
3982 | + { |
3983 | + "rlim_cur" : 0, |
3984 | + "rlim_max" : 0 |
3985 | + }, |
3986 | + { |
3987 | + "rlim_cur" : 0, |
3988 | + "rlim_max" : 0 |
3989 | + }, |
3990 | + { |
3991 | + "rlim_cur" : 0, |
3992 | + "rlim_max" : 0 |
3993 | + }, |
3994 | + { |
3995 | + "rlim_cur" : 0, |
3996 | + "rlim_max" : 0 |
3997 | + }, |
3998 | + { |
3999 | + "rlim_cur" : 0, |
4000 | + "rlim_max" : 0 |
4001 | + }, |
4002 | + { |
4003 | + "rlim_cur" : 0, |
4004 | + "rlim_max" : 0 |
4005 | + }, |
4006 | + { |
4007 | + "rlim_cur" : 0, |
4008 | + "rlim_max" : 0 |
4009 | + }, |
4010 | + { |
4011 | + "rlim_cur" : 0, |
4012 | + "rlim_max" : 0 |
4013 | + }, |
4014 | + { |
4015 | + "rlim_cur" : 0, |
4016 | + "rlim_max" : 0 |
4017 | + }, |
4018 | + { |
4019 | + "rlim_cur" : 0, |
4020 | + "rlim_max" : 0 |
4021 | + }, |
4022 | + { |
4023 | + "rlim_cur" : 0, |
4024 | + "rlim_max" : 0 |
4025 | + }, |
4026 | + { |
4027 | + "rlim_cur" : 0, |
4028 | + "rlim_max" : 0 |
4029 | + }, |
4030 | + { |
4031 | + "rlim_cur" : 0, |
4032 | + "rlim_max" : 0 |
4033 | + }, |
4034 | + { |
4035 | + "rlim_cur" : 0, |
4036 | + "rlim_max" : 0 |
4037 | + }, |
4038 | + { |
4039 | + "rlim_cur" : 0, |
4040 | + "rlim_max" : 0 |
4041 | + }, |
4042 | + { |
4043 | + "rlim_cur" : 0, |
4044 | + "rlim_max" : 0 |
4045 | + } |
4046 | + ], |
4047 | + "oom_score_adj" : 0, |
4048 | + "normalexit" : [], |
4049 | + "kill_timeout" : 5, |
4050 | + "usage" : null, |
4051 | + "env" : [ |
4052 | + "CRASH_DB_URL=https://daisy.ubuntu.com" |
4053 | + ], |
4054 | + "version" : null, |
4055 | + "task" : 0, |
4056 | + "path" : "/com/ubuntu/Upstart/jobs/whoopsie", |
4057 | + "deleted" : 0, |
4058 | + "chdir" : null, |
4059 | + "start_on" : "runlevel [2345]", |
4060 | + "umask" : 18, |
4061 | + "setgid" : null |
4062 | + }, |
4063 | + { |
4064 | + "setuid" : null, |
4065 | + "jobs" : [ |
4066 | + { |
4067 | + "trace_state" : "TRACE_NONE", |
4068 | + "failed" : 0, |
4069 | + "state" : "JOB_RUNNING", |
4070 | + "failed_process" : "PROCESS_INVALID", |
4071 | + "pid" : [ |
4072 | + 0, |
4073 | + 0, |
4074 | + 0, |
4075 | + 0, |
4076 | + 0, |
4077 | + 0 |
4078 | + ], |
4079 | + "start_env" : [], |
4080 | + "trace_forks" : 0, |
4081 | + "respawn_time" : 0, |
4082 | + "log" : [ |
4083 | + { |
4084 | + "path" : null |
4085 | + }, |
4086 | + { |
4087 | + "path" : null |
4088 | + }, |
4089 | + { |
4090 | + "path" : null |
4091 | + }, |
4092 | + { |
4093 | + "path" : null |
4094 | + }, |
4095 | + { |
4096 | + "path" : null |
4097 | + }, |
4098 | + { |
4099 | + "path" : null |
4100 | + } |
4101 | + ], |
4102 | + "respawn_count" : 0, |
4103 | + "kill_process" : "PROCESS_INVALID", |
4104 | + "stop_on" : "runlevel [!2345]", |
4105 | + "env" : [ |
4106 | + "PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin", |
4107 | + "TERM=linux", |
4108 | + "enabled=1", |
4109 | + "RUNLEVEL=2", |
4110 | + "PREVLEVEL=N", |
4111 | + "UPSTART_EVENTS=runlevel" |
4112 | + ], |
4113 | + "name" : "", |
4114 | + "path" : "/com/ubuntu/Upstart/jobs/apport/_", |
4115 | + "exit_status" : 0, |
4116 | + "goal" : "JOB_START", |
4117 | + "stop_env" : [], |
4118 | + "fds" : [] |
4119 | + } |
4120 | + ], |
4121 | + "emits" : [], |
4122 | + "session" : 0, |
4123 | + "debug" : 0, |
4124 | + "export" : [], |
4125 | + "expect" : "EXPECT_NONE", |
4126 | + "stop_on" : "runlevel [!2345]", |
4127 | + "chroot" : null, |
4128 | + "console" : "CONSOLE_LOG", |
4129 | + "kill_signal" : 15, |
4130 | + "name" : "apport", |
4131 | + "instance" : "", |
4132 | + "description" : "automatic crash report generation", |
4133 | + "respawn_interval" : 5, |
4134 | + "process" : [ |
4135 | + { |
4136 | + "script" : 0, |
4137 | + "command" : null |
4138 | + }, |
4139 | + { |
4140 | + "script" : 1, |
4141 | + "command" : " . /etc/default/apport\n [ \"$enabled\" = \"1\" ] || [ \"$force_start\" = \"1\" ] || exit 0\n\n mkdir -p -m 1777 /var/crash\n\n # check for kernel crash dump, convert it to apport report\n if [ -e /var/crash/vmcore ] || [ -n \"`ls /var/crash | egrep ^[0-9]{12}$`\" ]\n then\n\t/usr/share/apport/kernel_crashdump || true\n fi\n\n # check for incomplete suspend/resume or hibernate\n if [ -e /var/lib/pm-utils/status ]\n then\n /usr/share/apport/apportcheckresume || true\n rm -f /var/lib/pm-utils/status\n rm -f /var/lib/pm-utils/resume-hang.log\n fi\n\n echo \"|/usr/share/apport/apport %p %s %c\" > /proc/sys/kernel/core_pattern\n" |
4142 | + }, |
4143 | + { |
4144 | + "script" : 0, |
4145 | + "command" : null |
4146 | + }, |
4147 | + { |
4148 | + "script" : 0, |
4149 | + "command" : null |
4150 | + }, |
4151 | + { |
4152 | + "script" : 1, |
4153 | + "command" : " # Check for a hung resume. If we find one try and grab everything\n # we can to aid in its discovery\n if [ -e /var/lib/pm-utils/status ]\n then\n\tps -wwef > /var/lib/pm-utils/resume-hang.log\n fi\n\n if [ \"`dd if=/proc/sys/kernel/core_pattern count=1 bs=1 2>/dev/null`\" != \"|\" ]\n then\n\texit 1\n else\n\techo \"core\" > /proc/sys/kernel/core_pattern\n fi\n" |
4154 | + }, |
4155 | + { |
4156 | + "script" : 0, |
4157 | + "command" : null |
4158 | + } |
4159 | + ], |
4160 | + "apparmor_switch" : null, |
4161 | + "respawn_limit" : 10, |
4162 | + "author" : null, |
4163 | + "respawn" : 0, |
4164 | + "nice" : -21, |
4165 | + "limits" : [ |
4166 | + { |
4167 | + "rlim_cur" : 0, |
4168 | + "rlim_max" : 0 |
4169 | + }, |
4170 | + { |
4171 | + "rlim_cur" : 0, |
4172 | + "rlim_max" : 0 |
4173 | + }, |
4174 | + { |
4175 | + "rlim_cur" : 0, |
4176 | + "rlim_max" : 0 |
4177 | + }, |
4178 | + { |
4179 | + "rlim_cur" : 0, |
4180 | + "rlim_max" : 0 |
4181 | + }, |
4182 | + { |
4183 | + "rlim_cur" : 0, |
4184 | + "rlim_max" : 0 |
4185 | + }, |
4186 | + { |
4187 | + "rlim_cur" : 0, |
4188 | + "rlim_max" : 0 |
4189 | + }, |
4190 | + { |
4191 | + "rlim_cur" : 0, |
4192 | + "rlim_max" : 0 |
4193 | + }, |
4194 | + { |
4195 | + "rlim_cur" : 0, |
4196 | + "rlim_max" : 0 |
4197 | + }, |
4198 | + { |
4199 | + "rlim_cur" : 0, |
4200 | + "rlim_max" : 0 |
4201 | + }, |
4202 | + { |
4203 | + "rlim_cur" : 0, |
4204 | + "rlim_max" : 0 |
4205 | + }, |
4206 | + { |
4207 | + "rlim_cur" : 0, |
4208 | + "rlim_max" : 0 |
4209 | + }, |
4210 | + { |
4211 | + "rlim_cur" : 0, |
4212 | + "rlim_max" : 0 |
4213 | + }, |
4214 | + { |
4215 | + "rlim_cur" : 0, |
4216 | + "rlim_max" : 0 |
4217 | + }, |
4218 | + { |
4219 | + "rlim_cur" : 0, |
4220 | + "rlim_max" : 0 |
4221 | + }, |
4222 | + { |
4223 | + "rlim_cur" : 0, |
4224 | + "rlim_max" : 0 |
4225 | + }, |
4226 | + { |
4227 | + "rlim_cur" : 0, |
4228 | + "rlim_max" : 0 |
4229 | + } |
4230 | + ], |
4231 | + "oom_score_adj" : 0, |
4232 | + "normalexit" : [], |
4233 | + "kill_timeout" : 5, |
4234 | + "usage" : null, |
4235 | + "env" : [ |
4236 | + "enabled=1" |
4237 | + ], |
4238 | + "version" : null, |
4239 | + "task" : 0, |
4240 | + "path" : "/com/ubuntu/Upstart/jobs/apport", |
4241 | + "deleted" : 0, |
4242 | + "chdir" : null, |
4243 | + "start_on" : "runlevel [2345]", |
4244 | + "umask" : 18, |
4245 | + "setgid" : null |
4246 | + }, |
4247 | + { |
4248 | + "setuid" : null, |
4249 | + "jobs" : [ |
4250 | + { |
4251 | + "trace_state" : "TRACE_NONE", |
4252 | + "failed" : 0, |
4253 | + "state" : "JOB_RUNNING", |
4254 | + "failed_process" : "PROCESS_INVALID", |
4255 | + "pid" : [ |
4256 | + 628, |
4257 | + 0, |
4258 | + 0, |
4259 | + 0, |
4260 | + 0, |
4261 | + 0 |
4262 | + ], |
4263 | + "start_env" : [], |
4264 | + "trace_forks" : 0, |
4265 | + "respawn_time" : 0, |
4266 | + "log" : [ |
4267 | + { |
4268 | + "remote_closed" : 0, |
4269 | + "detached" : 0, |
4270 | + "uid" : 0, |
4271 | + "open_errno" : 9, |
4272 | + "path" : "/var/log/upstart/systemd-logind.log", |
4273 | + "io_watch_fd" : 17, |
4274 | + "fd" : 15 |
4275 | + }, |
4276 | + { |
4277 | + "path" : null |
4278 | + }, |
4279 | + { |
4280 | + "path" : null |
4281 | + }, |
4282 | + { |
4283 | + "path" : null |
4284 | + }, |
4285 | + { |
4286 | + "path" : null |
4287 | + }, |
4288 | + { |
4289 | + "path" : null |
4290 | + } |
4291 | + ], |
4292 | + "respawn_count" : 0, |
4293 | + "kill_process" : "PROCESS_INVALID", |
4294 | + "stop_on" : "stopping dbus", |
4295 | + "env" : [ |
4296 | + "PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin", |
4297 | + "TERM=linux", |
4298 | + "SYSTEMD_LOG_TARGET=syslog", |
4299 | + "JOB=dbus", |
4300 | + "INSTANCE=", |
4301 | + "UPSTART_EVENTS=started" |
4302 | + ], |
4303 | + "name" : "", |
4304 | + "path" : "/com/ubuntu/Upstart/jobs/systemd_2dlogind/_", |
4305 | + "exit_status" : 0, |
4306 | + "goal" : "JOB_START", |
4307 | + "stop_env" : [], |
4308 | + "fds" : [] |
4309 | + } |
4310 | + ], |
4311 | + "emits" : [], |
4312 | + "session" : 0, |
4313 | + "debug" : 0, |
4314 | + "export" : [], |
4315 | + "expect" : "EXPECT_NONE", |
4316 | + "stop_on" : "stopping dbus", |
4317 | + "chroot" : null, |
4318 | + "console" : "CONSOLE_LOG", |
4319 | + "kill_signal" : 15, |
4320 | + "name" : "systemd-logind", |
4321 | + "instance" : "", |
4322 | + "description" : "SystemD login management service", |
4323 | + "respawn_interval" : 5, |
4324 | + "process" : [ |
4325 | + { |
4326 | + "script" : 0, |
4327 | + "command" : "/lib/systemd/systemd-logind" |
4328 | + }, |
4329 | + { |
4330 | + "script" : 1, |
4331 | + "command" : " # only start if PAM module is actually available, not if libpam-systemd is\n # removed but not purged\n [ -e /lib/*/security/pam_systemd.so ] || { stop; exit 0; }\n\n # this is being done by systemd or mountall usually, but not during\n # upgrades from earlier distro releases\n if ! mountpoint -q /sys/fs/cgroup; then\n mount -t tmpfs -o uid=0,gid=0,mode=0755,size=1024 none /sys/fs/cgroup\n fi\n mkdir -p /run/systemd\n if ! mountpoint -q /sys/fs/cgroup/systemd; then\n mkdir -p /sys/fs/cgroup/systemd\n mount -t cgroup -o nosuid,noexec,nodev,none,name=systemd systemd /sys/fs/cgroup/systemd\n fi\n" |
4332 | + }, |
4333 | + { |
4334 | + "script" : 0, |
4335 | + "command" : null |
4336 | + }, |
4337 | + { |
4338 | + "script" : 0, |
4339 | + "command" : null |
4340 | + }, |
4341 | + { |
4342 | + "script" : 0, |
4343 | + "command" : null |
4344 | + }, |
4345 | + { |
4346 | + "script" : 0, |
4347 | + "command" : null |
4348 | + } |
4349 | + ], |
4350 | + "apparmor_switch" : null, |
4351 | + "respawn_limit" : 10, |
4352 | + "author" : null, |
4353 | + "respawn" : 1, |
4354 | + "nice" : -21, |
4355 | + "limits" : [ |
4356 | + { |
4357 | + "rlim_cur" : 0, |
4358 | + "rlim_max" : 0 |
4359 | + }, |
4360 | + { |
4361 | + "rlim_cur" : 0, |
4362 | + "rlim_max" : 0 |
4363 | + }, |
4364 | + { |
4365 | + "rlim_cur" : 0, |
4366 | + "rlim_max" : 0 |
4367 | + }, |
4368 | + { |
4369 | + "rlim_cur" : 0, |
4370 | + "rlim_max" : 0 |
4371 | + }, |
4372 | + { |
4373 | + "rlim_cur" : 0, |
4374 | + "rlim_max" : 0 |
4375 | + }, |
4376 | + { |
4377 | + "rlim_cur" : 0, |
4378 | + "rlim_max" : 0 |
4379 | + }, |
4380 | + { |
4381 | + "rlim_cur" : 0, |
4382 | + "rlim_max" : 0 |
4383 | + }, |
4384 | + { |
4385 | + "rlim_cur" : 16384, |
4386 | + "rlim_max" : 16384 |
4387 | + }, |
4388 | + { |
4389 | + "rlim_cur" : 0, |
4390 | + "rlim_max" : 0 |
4391 | + }, |
4392 | + { |
4393 | + "rlim_cur" : 0, |
4394 | + "rlim_max" : 0 |
4395 | + }, |
4396 | + { |
4397 | + "rlim_cur" : 0, |
4398 | + "rlim_max" : 0 |
4399 | + }, |
4400 | + { |
4401 | + "rlim_cur" : 0, |
4402 | + "rlim_max" : 0 |
4403 | + }, |
4404 | + { |
4405 | + "rlim_cur" : 0, |
4406 | + "rlim_max" : 0 |
4407 | + }, |
4408 | + { |
4409 | + "rlim_cur" : 0, |
4410 | + "rlim_max" : 0 |
4411 | + }, |
4412 | + { |
4413 | + "rlim_cur" : 0, |
4414 | + "rlim_max" : 0 |
4415 | + }, |
4416 | + { |
4417 | + "rlim_cur" : 0, |
4418 | + "rlim_max" : 0 |
4419 | + } |
4420 | + ], |
4421 | + "oom_score_adj" : 0, |
4422 | + "normalexit" : [], |
4423 | + "kill_timeout" : 5, |
4424 | + "usage" : null, |
4425 | + "env" : [ |
4426 | + "SYSTEMD_LOG_TARGET=syslog" |
4427 | + ], |
4428 | + "version" : null, |
4429 | + "task" : 0, |
4430 | + "path" : "/com/ubuntu/Upstart/jobs/systemd_2dlogind", |
4431 | + "deleted" : 0, |
4432 | + "chdir" : null, |
4433 | + "start_on" : "started dbus", |
4434 | + "umask" : 18, |
4435 | + "setgid" : null |
4436 | + }, |
4437 | + { |
4438 | + "setuid" : null, |
4439 | + "jobs" : [ |
4440 | + { |
4441 | + "trace_state" : "TRACE_NONE", |
4442 | + "failed" : 0, |
4443 | + "state" : "JOB_RUNNING", |
4444 | + "failed_process" : "PROCESS_INVALID", |
4445 | + "pid" : [ |
4446 | + 1032, |
4447 | + 0, |
4448 | + 0, |
4449 | + 0, |
4450 | + 0, |
4451 | + 0 |
4452 | + ], |
4453 | + "start_env" : [], |
4454 | + "trace_forks" : 0, |
4455 | + "respawn_time" : 0, |
4456 | + "log" : [ |
4457 | + { |
4458 | + "path" : null |
4459 | + }, |
4460 | + { |
4461 | + "path" : null |
4462 | + }, |
4463 | + { |
4464 | + "path" : null |
4465 | + }, |
4466 | + { |
4467 | + "path" : null |
4468 | + }, |
4469 | + { |
4470 | + "path" : null |
4471 | + }, |
4472 | + { |
4473 | + "path" : null |
4474 | + } |
4475 | + ], |
4476 | + "respawn_count" : 0, |
4477 | + "kill_process" : "PROCESS_INVALID", |
4478 | + "stop_on" : "runlevel [!23]", |
4479 | + "env" : [ |
4480 | + "PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin", |
4481 | + "TERM=linux", |
4482 | + "RUNLEVEL=2", |
4483 | + "PREVLEVEL=N", |
4484 | + "UPSTART_EVENTS=runlevel not-container" |
4485 | + ], |
4486 | + "name" : "", |
4487 | + "path" : "/com/ubuntu/Upstart/jobs/tty5/_", |
4488 | + "exit_status" : 0, |
4489 | + "goal" : "JOB_START", |
4490 | + "stop_env" : [], |
4491 | + "fds" : [] |
4492 | + } |
4493 | + ], |
4494 | + "emits" : [], |
4495 | + "session" : 0, |
4496 | + "debug" : 0, |
4497 | + "export" : [], |
4498 | + "expect" : "EXPECT_NONE", |
4499 | + "stop_on" : "runlevel [!23]", |
4500 | + "chroot" : null, |
4501 | + "console" : "CONSOLE_LOG", |
4502 | + "kill_signal" : 15, |
4503 | + "name" : "tty5", |
4504 | + "instance" : "", |
4505 | + "description" : null, |
4506 | + "respawn_interval" : 5, |
4507 | + "process" : [ |
4508 | + { |
4509 | + "script" : 0, |
4510 | + "command" : "/sbin/getty -8 38400 tty5" |
4511 | + }, |
4512 | + { |
4513 | + "script" : 0, |
4514 | + "command" : null |
4515 | + }, |
4516 | + { |
4517 | + "script" : 0, |
4518 | + "command" : null |
4519 | + }, |
4520 | + { |
4521 | + "script" : 0, |
4522 | + "command" : null |
4523 | + }, |
4524 | + { |
4525 | + "script" : 0, |
4526 | + "command" : null |
4527 | + }, |
4528 | + { |
4529 | + "script" : 0, |
4530 | + "command" : null |
4531 | + } |
4532 | + ], |
4533 | + "apparmor_switch" : null, |
4534 | + "respawn_limit" : 10, |
4535 | + "author" : null, |
4536 | + "respawn" : 1, |
4537 | + "nice" : -21, |
4538 | + "limits" : [ |
4539 | + { |
4540 | + "rlim_cur" : 0, |
4541 | + "rlim_max" : 0 |
4542 | + }, |
4543 | + { |
4544 | + "rlim_cur" : 0, |
4545 | + "rlim_max" : 0 |
4546 | + }, |
4547 | + { |
4548 | + "rlim_cur" : 0, |
4549 | + "rlim_max" : 0 |
4550 | + }, |
4551 | + { |
4552 | + "rlim_cur" : 0, |
4553 | + "rlim_max" : 0 |
4554 | + }, |
4555 | + { |
4556 | + "rlim_cur" : 0, |
4557 | + "rlim_max" : 0 |
4558 | + }, |
4559 | + { |
4560 | + "rlim_cur" : 0, |
4561 | + "rlim_max" : 0 |
4562 | + }, |
4563 | + { |
4564 | + "rlim_cur" : 0, |
4565 | + "rlim_max" : 0 |
4566 | + }, |
4567 | + { |
4568 | + "rlim_cur" : 0, |
4569 | + "rlim_max" : 0 |
4570 | + }, |
4571 | + { |
4572 | + "rlim_cur" : 0, |
4573 | + "rlim_max" : 0 |
4574 | + }, |
4575 | + { |
4576 | + "rlim_cur" : 0, |
4577 | + "rlim_max" : 0 |
4578 | + }, |
4579 | + { |
4580 | + "rlim_cur" : 0, |
4581 | + "rlim_max" : 0 |
4582 | + }, |
4583 | + { |
4584 | + "rlim_cur" : 0, |
4585 | + "rlim_max" : 0 |
4586 | + }, |
4587 | + { |
4588 | + "rlim_cur" : 0, |
4589 | + "rlim_max" : 0 |
4590 | + }, |
4591 | + { |
4592 | + "rlim_cur" : 0, |
4593 | + "rlim_max" : 0 |
4594 | + }, |
4595 | + { |
4596 | + "rlim_cur" : 0, |
4597 | + "rlim_max" : 0 |
4598 | + }, |
4599 | + { |
4600 | + "rlim_cur" : 0, |
4601 | + "rlim_max" : 0 |
4602 | + } |
4603 | + ], |
4604 | + "oom_score_adj" : 0, |
4605 | + "normalexit" : [], |
4606 | + "kill_timeout" : 5, |
4607 | + "usage" : null, |
4608 | + "env" : [], |
4609 | + "version" : null, |
4610 | + "task" : 0, |
4611 | + "path" : "/com/ubuntu/Upstart/jobs/tty5", |
4612 | + "deleted" : 0, |
4613 | + "chdir" : null, |
4614 | + "start_on" : "(runlevel [23] and not-container)", |
4615 | + "umask" : 18, |
4616 | + "setgid" : null |
4617 | + }, |
4618 | + { |
4619 | + "setuid" : null, |
4620 | + "jobs" : [ |
4621 | + { |
4622 | + "trace_state" : "TRACE_NONE", |
4623 | + "failed" : 0, |
4624 | + "state" : "JOB_RUNNING", |
4625 | + "failed_process" : "PROCESS_INVALID", |
4626 | + "pid" : [ |
4627 | + 819, |
4628 | + 0, |
4629 | + 0, |
4630 | + 0, |
4631 | + 0, |
4632 | + 0 |
4633 | + ], |
4634 | + "start_env" : [], |
4635 | + "trace_forks" : 0, |
4636 | + "respawn_time" : 0, |
4637 | + "log" : [ |
4638 | + { |
4639 | + "remote_closed" : 0, |
4640 | + "detached" : 0, |
4641 | + "uid" : 0, |
4642 | + "open_errno" : 9, |
4643 | + "path" : "/var/log/upstart/modemmanager.log", |
4644 | + "io_watch_fd" : 21, |
4645 | + "fd" : 14 |
4646 | + }, |
4647 | + { |
4648 | + "path" : null |
4649 | + }, |
4650 | + { |
4651 | + "path" : null |
4652 | + }, |
4653 | + { |
4654 | + "path" : null |
4655 | + }, |
4656 | + { |
4657 | + "path" : null |
4658 | + }, |
4659 | + { |
4660 | + "path" : null |
4661 | + } |
4662 | + ], |
4663 | + "respawn_count" : 0, |
4664 | + "kill_process" : "PROCESS_INVALID", |
4665 | + "stop_on" : "stopped network-manager", |
4666 | + "env" : [ |
4667 | + "PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin", |
4668 | + "TERM=linux", |
4669 | + "JOB=network-manager", |
4670 | + "INSTANCE=", |
4671 | + "UPSTART_EVENTS=starting" |
4672 | + ], |
4673 | + "name" : "", |
4674 | + "path" : "/com/ubuntu/Upstart/jobs/modemmanager/_", |
4675 | + "exit_status" : 0, |
4676 | + "goal" : "JOB_START", |
4677 | + "stop_env" : [], |
4678 | + "fds" : [] |
4679 | + } |
4680 | + ], |
4681 | + "emits" : [], |
4682 | + "session" : 0, |
4683 | + "debug" : 0, |
4684 | + "export" : [], |
4685 | + "expect" : "EXPECT_NONE", |
4686 | + "stop_on" : "stopped network-manager", |
4687 | + "chroot" : null, |
4688 | + "console" : "CONSOLE_LOG", |
4689 | + "kill_signal" : 15, |
4690 | + "name" : "modemmanager", |
4691 | + "instance" : "", |
4692 | + "description" : "modem connection manager", |
4693 | + "respawn_interval" : 5, |
4694 | + "process" : [ |
4695 | + { |
4696 | + "script" : 0, |
4697 | + "command" : "/usr/sbin/modem-manager" |
4698 | + }, |
4699 | + { |
4700 | + "script" : 1, |
4701 | + "command" : "[ -x /usr/sbin/modem-manager ] || stop\n" |
4702 | + }, |
4703 | + { |
4704 | + "script" : 0, |
4705 | + "command" : null |
4706 | + }, |
4707 | + { |
4708 | + "script" : 0, |
4709 | + "command" : null |
4710 | + }, |
4711 | + { |
4712 | + "script" : 0, |
4713 | + "command" : null |
4714 | + }, |
4715 | + { |
4716 | + "script" : 0, |
4717 | + "command" : null |
4718 | + } |
4719 | + ], |
4720 | + "apparmor_switch" : null, |
4721 | + "respawn_limit" : 10, |
4722 | + "author" : null, |
4723 | + "respawn" : 1, |
4724 | + "nice" : -21, |
4725 | + "limits" : [ |
4726 | + { |
4727 | + "rlim_cur" : 0, |
4728 | + "rlim_max" : 0 |
4729 | + }, |
4730 | + { |
4731 | + "rlim_cur" : 0, |
4732 | + "rlim_max" : 0 |
4733 | + }, |
4734 | + { |
4735 | + "rlim_cur" : 0, |
4736 | + "rlim_max" : 0 |
4737 | + }, |
4738 | + { |
4739 | + "rlim_cur" : 0, |
4740 | + "rlim_max" : 0 |
4741 | + }, |
4742 | + { |
4743 | + "rlim_cur" : 0, |
4744 | + "rlim_max" : 0 |
4745 | + }, |
4746 | + { |
4747 | + "rlim_cur" : 0, |
4748 | + "rlim_max" : 0 |
4749 | + }, |
4750 | + { |
4751 | + "rlim_cur" : 0, |
4752 | + "rlim_max" : 0 |
4753 | + }, |
4754 | + { |
4755 | + "rlim_cur" : 0, |
4756 | + "rlim_max" : 0 |
4757 | + }, |
4758 | + { |
4759 | + "rlim_cur" : 0, |
4760 | + "rlim_max" : 0 |
4761 | + }, |
4762 | + { |
4763 | + "rlim_cur" : 0, |
4764 | + "rlim_max" : 0 |
4765 | + }, |
4766 | + { |
4767 | + "rlim_cur" : 0, |
4768 | + "rlim_max" : 0 |
4769 | + }, |
4770 | + { |
4771 | + "rlim_cur" : 0, |
4772 | + "rlim_max" : 0 |
4773 | + }, |
4774 | + { |
4775 | + "rlim_cur" : 0, |
4776 | + "rlim_max" : 0 |
4777 | + }, |
4778 | + { |
4779 | + "rlim_cur" : 0, |
4780 | + "rlim_max" : 0 |
4781 | + }, |
4782 | + { |
4783 | + "rlim_cur" : 0, |
4784 | + "rlim_max" : 0 |
4785 | + }, |
4786 | + { |
4787 | + "rlim_cur" : 0, |
4788 | + "rlim_max" : 0 |
4789 | + } |
4790 | + ], |
4791 | + "oom_score_adj" : 0, |
4792 | + "normalexit" : [], |
4793 | + "kill_timeout" : 5, |
4794 | + "usage" : null, |
4795 | + "env" : [], |
4796 | + "version" : null, |
4797 | + "task" : 0, |
4798 | + "path" : "/com/ubuntu/Upstart/jobs/modemmanager", |
4799 | + "deleted" : 0, |
4800 | + "chdir" : null, |
4801 | + "start_on" : "starting network-manager", |
4802 | + "umask" : 18, |
4803 | + "setgid" : null |
4804 | + }, |
4805 | + { |
4806 | + "setuid" : null, |
4807 | + "jobs" : [ |
4808 | + { |
4809 | + "trace_state" : "TRACE_NONE", |
4810 | + "failed" : 0, |
4811 | + "state" : "JOB_RUNNING", |
4812 | + "failed_process" : "PROCESS_INVALID", |
4813 | + "pid" : [ |
4814 | + 0, |
4815 | + 0, |
4816 | + 0, |
4817 | + 0, |
4818 | + 0, |
4819 | + 0 |
4820 | + ], |
4821 | + "start_env" : [], |
4822 | + "trace_forks" : 0, |
4823 | + "respawn_time" : 0, |
4824 | + "log" : [ |
4825 | + { |
4826 | + "path" : null |
4827 | + }, |
4828 | + { |
4829 | + "path" : null |
4830 | + }, |
4831 | + { |
4832 | + "path" : null |
4833 | + }, |
4834 | + { |
4835 | + "path" : null |
4836 | + }, |
4837 | + { |
4838 | + "path" : null |
4839 | + }, |
4840 | + { |
4841 | + "path" : null |
4842 | + } |
4843 | + ], |
4844 | + "respawn_count" : 0, |
4845 | + "kill_process" : "PROCESS_INVALID", |
4846 | + "env" : [ |
4847 | + "PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin", |
4848 | + "TERM=linux", |
4849 | + "UPSTART_EVENTS=local-filesystems" |
4850 | + ], |
4851 | + "name" : "", |
4852 | + "path" : "/com/ubuntu/Upstart/jobs/mountall_2esh/_", |
4853 | + "exit_status" : 0, |
4854 | + "goal" : "JOB_START", |
4855 | + "stop_env" : [], |
4856 | + "fds" : [] |
4857 | + } |
4858 | + ], |
4859 | + "emits" : [], |
4860 | + "session" : 0, |
4861 | + "debug" : 0, |
4862 | + "export" : [], |
4863 | + "expect" : "EXPECT_NONE", |
4864 | + "chroot" : null, |
4865 | + "console" : "CONSOLE_LOG", |
4866 | + "kill_signal" : 15, |
4867 | + "name" : "mountall.sh", |
4868 | + "instance" : "", |
4869 | + "description" : "Signal sysvinit that local filesystems are mounted", |
4870 | + "respawn_interval" : 5, |
4871 | + "process" : [ |
4872 | + { |
4873 | + "script" : 0, |
4874 | + "command" : null |
4875 | + }, |
4876 | + { |
4877 | + "script" : 0, |
4878 | + "command" : null |
4879 | + }, |
4880 | + { |
4881 | + "script" : 0, |
4882 | + "command" : null |
4883 | + }, |
4884 | + { |
4885 | + "script" : 0, |
4886 | + "command" : null |
4887 | + }, |
4888 | + { |
4889 | + "script" : 0, |
4890 | + "command" : null |
4891 | + }, |
4892 | + { |
4893 | + "script" : 0, |
4894 | + "command" : null |
4895 | + } |
4896 | + ], |
4897 | + "apparmor_switch" : null, |
4898 | + "respawn_limit" : 10, |
4899 | + "author" : null, |
4900 | + "respawn" : 0, |
4901 | + "nice" : -21, |
4902 | + "limits" : [ |
4903 | + { |
4904 | + "rlim_cur" : 0, |
4905 | + "rlim_max" : 0 |
4906 | + }, |
4907 | + { |
4908 | + "rlim_cur" : 0, |
4909 | + "rlim_max" : 0 |
4910 | + }, |
4911 | + { |
4912 | + "rlim_cur" : 0, |
4913 | + "rlim_max" : 0 |
4914 | + }, |
4915 | + { |
4916 | + "rlim_cur" : 0, |
4917 | + "rlim_max" : 0 |
4918 | + }, |
4919 | + { |
4920 | + "rlim_cur" : 0, |
4921 | + "rlim_max" : 0 |
4922 | + }, |
4923 | + { |
4924 | + "rlim_cur" : 0, |
4925 | + "rlim_max" : 0 |
4926 | + }, |
4927 | + { |
4928 | + "rlim_cur" : 0, |
4929 | + "rlim_max" : 0 |
4930 | + }, |
4931 | + { |
4932 | + "rlim_cur" : 0, |
4933 | + "rlim_max" : 0 |
4934 | + }, |
4935 | + { |
4936 | + "rlim_cur" : 0, |
4937 | + "rlim_max" : 0 |
4938 | + }, |
4939 | + { |
4940 | + "rlim_cur" : 0, |
4941 | + "rlim_max" : 0 |
4942 | + }, |
4943 | + { |
4944 | + "rlim_cur" : 0, |
4945 | + "rlim_max" : 0 |
4946 | + }, |
4947 | + { |
4948 | + "rlim_cur" : 0, |
4949 | + "rlim_max" : 0 |
4950 | + }, |
4951 | + { |
4952 | + "rlim_cur" : 0, |
4953 | + "rlim_max" : 0 |
4954 | + }, |
4955 | + { |
4956 | + "rlim_cur" : 0, |
4957 | + "rlim_max" : 0 |
4958 | + }, |
4959 | + { |
4960 | + "rlim_cur" : 0, |
4961 | + "rlim_max" : 0 |
4962 | + }, |
4963 | + { |
4964 | + "rlim_cur" : 0, |
4965 | + "rlim_max" : 0 |
4966 | + } |
4967 | + ], |
4968 | + "oom_score_adj" : 0, |
4969 | + "normalexit" : [], |
4970 | + "kill_timeout" : 5, |
4971 | + "usage" : null, |
4972 | + "env" : [], |
4973 | + "version" : null, |
4974 | + "task" : 0, |
4975 | + "path" : "/com/ubuntu/Upstart/jobs/mountall_2esh", |
4976 | + "deleted" : 0, |
4977 | + "chdir" : null, |
4978 | + "start_on" : "local-filesystems", |
4979 | + "umask" : 18, |
4980 | + "setgid" : null |
4981 | + }, |
4982 | + { |
4983 | + "setuid" : null, |
4984 | + "jobs" : [ |
4985 | + { |
4986 | + "trace_state" : "TRACE_NONE", |
4987 | + "failed" : 0, |
4988 | + "state" : "JOB_RUNNING", |
4989 | + "failed_process" : "PROCESS_INVALID", |
4990 | + "pid" : [ |
4991 | + 1136, |
4992 | + 0, |
4993 | + 0, |
4994 | + 0, |
4995 | + 0, |
4996 | + 0 |
4997 | + ], |
4998 | + "start_env" : [], |
4999 | + "trace_forks" : 1, |
5000 | + "respawn_time" : 0, |
Something looks wrong with this branch, commit 1481 should probably have been a rebase instead of merging trunk into a branch that you then want to merge into trunk. BZR won't fail to merge this but the history will look a bit weird.
You appear to be using "iff" in quite a few places (including some other occurrences in current lp:upstart) are those actually meant as "if and only if" or are those typos (or a mix of the two)?
Besides those two small details, nothing jumped at me during a quick read through of the diff. However this is a massive change so I won't pretend to have done a careful review of it. deserialization bits make sense and match.
I mostly rechecked the concept based on the very detailed comments you left in the code and checked that the serialization/