Merge lp:~xnox/ubuntu/utopic/sysvinit/upstart-task into lp:ubuntu/utopic/sysvinit

Proposed by Dimitri John Ledkov
Status: Rejected
Rejected by: Martin Pitt
Proposed branch: lp:~xnox/ubuntu/utopic/sysvinit/upstart-task
Merge into: lp:ubuntu/utopic/sysvinit
Diff against target: 812 lines (+739/-4) (has conflicts)
7 files modified
.pc/applied-patches (+1/-0)
.pc/startpar-upstart-tasks.patch/startpar/makeboot.c (+688/-0)
debian/changelog (+10/-0)
debian/patches/series (+1/-0)
debian/patches/startpar-upstart-tasks.patch (+28/-0)
debian/src/sysv-rc/etc/init.d/rc (+1/-3)
startpar/makeboot.c (+10/-1)
Text conflict in debian/changelog
To merge this branch: bzr merge lp:~xnox/ubuntu/utopic/sysvinit/upstart-task
Reviewer Review Type Date Requested Status
Martin Pitt Needs Fixing
Adam Conrad Pending
Stéphane Graber Pending
Steve Langasek Pending
Ubuntu branches Pending
Review via email: mp+221493@code.launchpad.net

Description of the change

Some of the init.d scripts have been converted to tasks. Given the way ubuntu boots (e.g. udev based assembly of lvm/raid etc); and the fact that upstart-native tasks are typically complete before invoking rc; and no way to tell that an upstart task has been run. It should be sufficient to consider all task jobs as complete from startpar bridge point of view, and thus not block rc, waiting to execute a task job.

To post a comment you must log in.
Revision history for this message
Martin Pitt (pitti) wrote :

The way I understand it the really clean way to implement this would be to tell apart the case "this task job never ran" from "it ran at least once, but is stopped". This could either be by a different status message (like "stop/waiting" vs. "finished/waiting", or similar), or creating a stamp file in /run for every ran task. Both of which would be upstart changes.

This also introduces the assumption that upstart's tasks will always run before startpar so that the init.d dependencies will always be satisfied for tasks. That's not quite correct and sounds like introducing race conditions.

That said, if this is supposed to be a better workaround instead of an actual solution, it seems ok to me for the time being. It's at least better than running all init.d scripts.

Thanks!

Revision history for this message
Steve Langasek (vorlon) wrote :

On Fri, May 30, 2014 at 08:19:15AM -0000, Martin Pitt wrote:
> The way I understand it the really clean way to implement this would be to
> tell apart the case "this task job never ran" from "it ran at least once,
> but is stopped". This could either be by a different status message (like
> "stop/waiting" vs. "finished/waiting", or similar), or creating a stamp
> file in /run for every ran task. Both of which would be upstart changes.

> This also introduces the assumption that upstart's tasks will always run
> before startpar so that the init.d dependencies will always be satisfied
> for tasks. That's not quite correct and sounds like introducing race
> conditions.

In practice, *everything* in /etc/rcS.d is supposed to be redundant with
upstart jobs in the upstart case, and the impact of a race condition - as
opposed to hang - should be nil.

If we have task jobs that map to scripts in /etc/rc2.d, I think we should
take a close look at this. However, for the "unofficial upstart jobs" case,
I don't think we should put the effort into ensuring there are no race
conditions when the user has both created an upstart task job that conflicts
with an init script *and* has another init script depending on that first
task. Clearly we would want to address this if we were sticking with
upstart longer-term, but I don't think it's relevant on a transitional
basis.

Revision history for this message
Steve Langasek (vorlon) wrote :

> --- startpar/makeboot.c 2012-06-27 23:00:45 +0000
> +++ startpar/makeboot.c 2014-05-30 07:54:58 +0000
> @@ -451,6 +451,13 @@
> t->name);
> }
> ret = system(command);
> + if (WEXITSTATUS(ret) != 0) {
> + free(command);
> + asprintf(&command,
> + "grep -q '^task$' %s",
> + path);
> + ret = system(command);
> + }
> if (WEXITSTATUS(ret) == 0) {
> nodevec[count] = t;
> finish_task(t);
>

This appears to give task jobs a free pass both when checking if they're
started, but also when checking if they're stopped. The reason for making
this change is because we can't detect if a task has run and already stopped
again; but if it's currently running we can certainly detect that. Should
we do so, to avoid letting an init script be called on shutdown while a task
is still running?

I had a look at the code around timeouts in startpar, and don't think it's
worth trying to hook the task handling up to it for what should be a
short-term solution.

209. By Dimitri John Ledkov

Give tasks a free-pass on boot only.

Revision history for this message
Martin Pitt (pitti) wrote :

This updated version looks ok to me as per the discussion above. I'd still like the ^task$ to be extended to allow whitespace (as I suggested in my previous inline diff comments, but they might have drowned). Also, I think this should revert http://launchpadlibrarian.net/176540378/sysvinit_2.88dsf-41ubuntu14_2.88dsf-41ubuntu15.diff.gz at the same time. Finally, I think it makes more sense to fold this into the existing debian/patches/upstart_support.patch instead of yet another patch (but fine for now for experimentation).

I built this branch with CONCURRENCY back to "makefile" so that this has any effect. But now my VM hangs at early shutdown, and also I don't see anything at all during boot (even without "quiet splash"), so something is still wrong here. In which environment did you try this?

Thanks!

review: Needs Fixing
210. By Dimitri John Ledkov

Improve task grep pattern.

211. By Dimitri John Ledkov

Re-enable startpar.

Revision history for this message
Martin Pitt (pitti) wrote :

Setting to work in progress for now, to get it out of the sponsoring queue. However, we might just bury this completely, as we discussed to not support startpar after all? It'd be more trouble than it's worth IMHO. So please feel free to delete this.

Revision history for this message
Martin Pitt (pitti) wrote :

I think it's safe to say that we won't pursue this direction. We disabled startpar support in sysvinit and removed startpar from the archive.

Unmerged revisions

211. By Dimitri John Ledkov

Re-enable startpar.

210. By Dimitri John Ledkov

Improve task grep pattern.

209. By Dimitri John Ledkov

Give tasks a free-pass on boot only.

208. By Dimitri John Ledkov

Add 'task' knowledge to startpar.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '.pc/applied-patches'
--- .pc/applied-patches 2013-05-17 20:53:22 +0000
+++ .pc/applied-patches 2014-06-05 13:25:18 +0000
@@ -23,3 +23,4 @@
2393_run_initctl.patch2393_run_initctl.patch
2494_kfreebsd_xterm.patch2494_kfreebsd_xterm.patch
25upstart_support.patch25upstart_support.patch
26startpar-upstart-tasks.patch
2627
=== added directory '.pc/startpar-upstart-tasks.patch'
=== added directory '.pc/startpar-upstart-tasks.patch/startpar'
=== added file '.pc/startpar-upstart-tasks.patch/startpar/makeboot.c'
--- .pc/startpar-upstart-tasks.patch/startpar/makeboot.c 1970-01-01 00:00:00 +0000
+++ .pc/startpar-upstart-tasks.patch/startpar/makeboot.c 2014-06-05 13:25:18 +0000
@@ -0,0 +1,688 @@
1/*
2 * very very simple makefile parser
3 *
4 * Copyright (c) 2003 SuSE Linux AG
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program (see the file COPYING); if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 *
21 */
22
23#include <stdio.h>
24#include <stddef.h>
25#include <string.h>
26#include <malloc.h>
27#include <ctype.h>
28#include <stdlib.h>
29#include <dirent.h>
30#include <unistd.h>
31#include <stdarg.h>
32#include <errno.h>
33#include <limits.h>
34#include <sys/socket.h>
35#include <sys/un.h>
36#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
37# include <sys/types.h>
38# include <sys/stat.h>
39# include <fcntl.h>
40#ifndef POSIX_FADV_SEQUENTIAL
41#define posix_fadvise(fd, off, len, adv) (-1)
42#endif
43#ifndef O_DIRECT
44#define O_DIRECT 0
45#endif
46static int o_flags = O_RDONLY;
47#endif
48#ifdef USE_BLOGD
49# include <libblogger.h>
50#endif
51#include "makeboot.h"
52
53#define DBUS_ADDRESS_UPSTART "@/com/ubuntu/upstart"
54
55int tree_entries = 0;
56struct makenode *tree_list = NULL;
57
58/*
59 * search for the node with the given name
60 * returns the node pointer or NULL if not found.
61 *
62 * FIXME: we should use hash for the effective search.
63 */
64struct makenode *lookup_target(const char *name)
65{
66 struct makenode *t;
67
68 for (t = tree_list; t; t = t->next)
69 if (! strcmp(t->name, name))
70 return t;
71 return NULL;
72}
73
74/*
75 * look for the node with the given name. if not exist,
76 * create a new one and append to the node list.
77 */
78static struct makenode *add_target(const char *name)
79{
80 struct makenode *__restrict node;
81 struct makenode *prev, *t;
82
83 node = lookup_target(name);
84 if (node)
85 return node;
86 if (posix_memalign((void*)&node, sizeof(void*), alignof(struct makenode)+strsize(name)) < 0) {
87 fprintf(stderr, "Can't malloc: %s\n", strerror(errno));
88 exit(1);
89 }
90 memset(node, 0, alignof(struct makenode)+strsize(name));
91 node->name = ((char*)node)+alignof(struct makenode);
92 strcpy(node->name, name);
93
94 /* append to the list in alphabetical order */
95 prev = NULL;
96 for (t = tree_list; t; prev = t, t = t->next)
97 if (strcmp(node->name, t->name) < 0)
98 break;
99 if (prev)
100 prev->next = node;
101 else
102 tree_list = node;
103 node->next = t;
104 tree_entries++;
105 return node;
106}
107
108/*
109 * Set and propagate importance of a node to all depencies of this node
110 */
111static void add_importance(struct makenode *node, int importance)
112{
113 struct makelist *s = node->depend;
114
115 node->importance += importance;
116 for (s = node->depend; s; s = s->next)
117 add_importance(s->node, importance);
118}
119
120/*
121 * create a dependecy/selection node
122 */
123static struct makelist *new_list(struct makenode *node, struct makelist *next)
124{
125 struct makelist *x;
126
127 x = xcalloc(1, sizeof(*x));
128 x->node = node;
129 x->next = next;
130 return x;
131}
132
133/*
134 * check whether the given target would create an infinte loop
135 */
136static int loop;
137static int check_loop(struct makenode *dep, struct makenode *src)
138{
139 struct makelist *s;
140 for (s = dep->depend; s; s = s->next) {
141 if (s->node == src) {
142 fprintf(stderr, "loop exists %s in %s!\n", dep->name, src->name);
143 return 1;
144 }
145 if (loop++ > 99999) {
146 fprintf(stderr, "too many loops! (loop=%d, dep->name=%s, src->name=%s)\n",
147 loop, dep->name, src->name);
148 return 1;
149 }
150 if (check_loop(s->node, src))
151 return 1;
152 }
153 return 0;
154}
155
156/*
157 * add to the dependecy and selection lists
158 */
159static void add_depend(struct makenode *node, const char *dst)
160{
161 struct makenode *dep;
162
163 dep = add_target(dst);
164 loop = 0;
165 if (check_loop(dep, node))
166 return;
167 dep->select = new_list(node, dep->select);
168 dep->num_sels++;
169 node->depend = new_list(dep, node->depend);
170 node->num_deps++;
171}
172
173/*
174 * mark the selected service as an interactive task
175 * that should run solely
176 */
177static void mark_interactive(const char *name)
178{
179 struct makenode *node = lookup_target(name);
180 if (node)
181 node->interactive = 1;
182}
183
184
185#define DELIMITER " \t\r\n"
186
187/*
188 * parse (pseudo) makefile
189 *
190 * it may have only the following form:
191 *
192 * TARGETS = xxx ...
193 * INTERACTIVE = yyy ...
194 * aaa:
195 * bbb: xxx ddd ...
196 *
197 * other lines are ignored.
198 */
199void parse_makefile(const char *path)
200{
201 FILE *fp;
202 char buf[LINE_MAX]; /* FIXME: is this enough big? */
203 char *s, *strp, *p;
204 struct makenode *node;
205
206#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
207 int fd;
208
209 if (getuid() == (uid_t)0)
210 o_flags |= O_NOATIME;
211 if ((fd = open(path, o_flags)) < 0) {
212 fprintf(stderr, "Can't open %s: %s\n", path, strerror(errno));
213 exit(1);
214 }
215 (void)posix_fadvise(fd, 0, 0, POSIX_FADV_WILLNEED);
216 (void)posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
217 (void)posix_fadvise(fd, 0, 0, POSIX_FADV_NOREUSE);
218
219 if ((fp = fdopen(fd, "r")) == NULL)
220#else
221 if ((fp = fopen(path, "r")) == NULL)
222#endif
223 {
224 fprintf(stderr, "Can't open %s: %s\n", path, strerror(errno));
225 exit(1);
226 }
227
228 while (fgets(buf, sizeof(buf), fp)) {
229 for (s = buf; *s && isspace(*s); s++)
230 ;
231 if (! *s || *s == '#')
232 continue;
233 if (! strncmp(s, "TARGETS =", 9)) {
234 s += 9;
235 strp = s;
236 while ((s = strsep(&strp, DELIMITER))) {
237 if (! *s)
238 continue;
239 add_target(s);
240 }
241 } else if (! strncmp(s, "INTERACTIVE =", 13)) {
242 s += 13;
243 strp = s;
244 while ((s = strsep(&strp, DELIMITER))) {
245 if (! *s)
246 continue;
247 mark_interactive(s);
248 }
249 } else {
250 p = strchr(s, ':');
251 if (! p)
252 continue;
253 *p = 0;
254 node = add_target(s);
255 strp = p + 1;
256 while ((s = strsep(&strp, DELIMITER))) {
257 if (! *s)
258 continue;
259 add_depend(node, s);
260 }
261 }
262 }
263
264#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
265 (void)posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
266#endif
267
268 fclose(fp);
269
270 for (node = tree_list; node; node = node->next) {
271 int importance = 0;
272
273 if (! strcmp(node->name, "xdm")
274 || ! strncmp(node->name, "gdm", 3)
275 || ! strncmp(node->name, "kdm", 3)
276 || ! strcmp(node->name, "boot.udev")
277 || ! strcmp(node->name, "udev"))
278 importance = 100;
279
280 if (! strcmp(node->name, "sshd"))
281 importance = 2000;
282
283 if (! strncmp(node->name, "early", 5))
284 importance = 8000;
285
286 if (importance)
287 add_importance(node, importance);
288 }
289}
290
291/*
292 * filter out the list targets
293 */
294
295static int filter_prefix;
296static int dirfilter(const struct dirent *d)
297{
298 return *d->d_name == filter_prefix &&
299 strlen(d->d_name) >= 4; /* to be sure */
300}
301
302static void filter_files(const char *dir, int prefix, int inverse)
303{
304 char path[64];
305 int i, ndirs;
306 static struct dirent **dirlist;
307 struct makenode *t, *next;
308
309 filter_prefix = prefix;
310#ifdef SUSE /* SuSE */
311 snprintf(path, sizeof(path), "/etc/init.d/%s.d", dir);
312#else /* Debian */
313 snprintf(path, sizeof(path), "/etc/%s.d", dir);
314#endif
315#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
316 if ((i = open(path, o_flags|O_DIRECTORY|O_LARGEFILE)) >= 0) {
317 (void)posix_fadvise(i, 0, 0, POSIX_FADV_SEQUENTIAL);
318 (void)posix_fadvise(i, 0, 0, POSIX_FADV_NOREUSE);
319 }
320#endif
321 ndirs = scandir(path, &dirlist, dirfilter, alphasort);
322#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
323 if (i >= 0) {
324 (void)posix_fadvise(i, 0, 0, POSIX_FADV_DONTNEED);
325 close(i);
326 }
327#endif
328 /* mark all matching nodes */
329 if (ndirs >= 0) {
330 for (i = 0; i < ndirs; i++) {
331 t = lookup_target(dirlist[i]->d_name + 3);
332 if (t) {
333 t->status = 1;
334 t->filter_prefix = filter_prefix;
335 if (asprintf(&t->arg0, "%s/%s", path, dirlist[i]->d_name) < 0)
336 t->arg0 = (char*)0;
337 }
338 free(dirlist[i]);
339 }
340 free(dirlist);
341 }
342 /* deselect non-matching nodes */
343 for (t = tree_list; t; t = next) {
344 next = t->next;
345 if ((! t->status && ! inverse) || (t->status && inverse)) {
346 /* remove from the list */
347 struct makelist *x, *nx;
348 struct makenode *p;
349 for (x = t->select; x; x = nx) {
350 nx = x->next;
351 x->node->num_deps--;
352 free(x);
353 }
354 for (x = t->depend; x; x = nx) {
355 nx = x->next;
356 x->node->num_sels--;
357 free(x);
358 }
359 if (t == tree_list)
360 tree_list = next;
361 else {
362 for (p = tree_list; p->next != t; p = p->next)
363 ;
364 p->next = next;
365 }
366 /* don't free the node instance itself - it may be selected
367 * by others
368 */
369 tree_entries--;
370 continue;
371 }
372 t->status = 0;
373 }
374}
375
376/*
377 * mark the unnecessary services as finished.
378 *
379 * action is either boot, start or stop.
380 * prev and run are the previous and the next runlevel.
381 */
382void check_run_files(const char *action, const char *prev, const char *run)
383{
384 char buf[4] = "rc0";
385 if (! strcmp(action, "boot")) {
386#ifdef SUSE /* SuSE */
387 filter_files("boot", 'S', 0);
388 } else if (! strcmp(action, "halt")) {
389 filter_files("boot", 'K', 0);
390 } else if (! strcmp(action, "start")) {
391 buf[2] = *prev;
392 filter_files(buf, 'K', 1);
393 buf[2] = *run;
394 filter_files(buf, 'S', 0);
395 } else {
396 buf[2] = *prev;
397 filter_files(buf, 'K', 0);
398 buf[2] = *run;
399 filter_files(buf, 'S', 1);
400#else /* Debian */
401 filter_files("rcS", 'S', 0);
402 } else if (! strcmp(action, "start")) {
403 buf[2] = *prev;
404 filter_files(buf, 'S', 1);
405 buf[2] = *run;
406 filter_files(buf, 'S', 0);
407 } else {
408 buf[2] = *prev;
409 filter_files(buf, 'K', 1);
410 buf[2] = *run;
411 filter_files(buf, 'K', 0);
412#endif
413 }
414}
415
416#ifdef __linux__
417/*
418 * mark upstart services as finished.
419 *
420 * action is either boot, start or stop.
421 */
422int check_upstart_jobs(const char *action, const struct makenode **nodevec)
423{
424 struct makenode *t;
425 int count = 0;
426
427 if (!init_is_upstart())
428 return 0;
429
430 for (t = tree_list; t; t = t->next)
431 {
432 char path[131]; /* three bytes longer than the max allowed init script name... */
433 struct stat job;
434
435 snprintf(path, sizeof(path), "/etc/init/%s.conf", t->name);
436 if (!stat(path,&job)) {
437 int ret;
438 char *command;
439
440 t->upstart = 1;
441 /* Upstart jobs are never interactive in this sense */
442 t->interactive = 0;
443 if (!strcmp(action,"start") || !strcmp(action,"boot"))
444 {
445 asprintf(&command,
446 "/sbin/initctl status %s | grep -q start/running",
447 t->name);
448 } else {
449 asprintf(&command,
450 "/sbin/initctl status %s | grep -q stop/waiting",
451 t->name);
452 }
453 ret = system(command);
454 if (WEXITSTATUS(ret) == 0) {
455 nodevec[count] = t;
456 finish_task(t);
457 count++;
458 }
459 free(command);
460 }
461 }
462 return count;
463}
464
465/*
466 * return true if PID 1 is upstart, false otherwise.
467 */
468boolean init_is_upstart(void) {
469 static int is_upstart = -1;
470 int fd;
471 struct sockaddr_un saddr;
472 socklen_t addrlen;
473 struct ucred ucred;
474 socklen_t slen;
475
476 if (is_upstart != -1)
477 return is_upstart;
478
479 fd = socket(AF_LOCAL, SOCK_STREAM, 0);
480 /* Weird, but we'll just have to assume no upstart. */
481 if (fd < 0)
482 goto fail;
483
484 saddr.sun_family = AF_LOCAL;
485 strcpy(saddr.sun_path, DBUS_ADDRESS_UPSTART);
486 addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path);
487
488 /* translate leading '@' to abstract namespace */
489 if (saddr.sun_path[0] == '@')
490 saddr.sun_path[0] = '\0';
491
492 if (connect(fd, (struct sockaddr *)&saddr, addrlen) < 0)
493 goto fail;
494
495 /* Make sure it's really upstart and not something lying to us! */
496 slen = sizeof(ucred);
497 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &slen) < 0)
498 goto fail;
499
500 close(fd);
501 if (ucred.uid == 0)
502 is_upstart = 1;
503 else
504 is_upstart = 0;
505
506 return is_upstart;
507
508fail:
509 if (fd >= 0)
510 close(fd);
511 is_upstart = 0;
512 return is_upstart;
513}
514#endif
515
516/*
517 * call blogd
518 */
519#ifndef USE_BLOGD
520# define bootlog(arg...)
521# define closeblog()
522#endif
523
524/*
525 * pick up the next running task
526 * return NULL if not found.
527 */
528struct makenode *pickup_task(void)
529{
530 struct makenode *node, *best = (struct makenode*)0;
531
532 for (node = tree_list; node; node = node->next) {
533 if (node->status != T_READY)
534 continue;
535 if (node->num_deps > 0)
536 continue;
537 if (!best || (node->importance > best->importance))
538 best = node;
539 }
540 if (best) {
541#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
542 char path[128];
543 int fd;
544 snprintf(path, sizeof(path), "/etc/init.d/%s", best->name);
545 if ((fd = open(path, o_flags|O_DIRECT)) >= 0) {
546 (void)posix_fadvise(fd, 0, 0, POSIX_FADV_WILLNEED);
547 (void)posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
548 (void)posix_fadvise(fd, 0, 0, POSIX_FADV_NOREUSE);
549 close(fd);
550 }
551#endif
552 bootlog(B_NOTICE, "service %s %s", best->name, (best->filter_prefix == 'K') ? "stop" : "start");
553 best->status = T_RUNNING;
554 }
555 return best;
556}
557
558/*
559 * finish the running task
560 */
561void finish_task(struct makenode *node)
562{
563 struct makelist *n;
564
565 if (! node)
566 return;
567 /* Ignore any further upstart signals for this job */
568 node->upstart = 0;
569 for (n = node->select; n; n = n->next)
570 n->node->num_deps--;
571#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
572 {
573 char path[128];
574 int fd;
575 snprintf(path, sizeof(path), "/etc/init.d/%s", node->name);
576 if ((fd = open(path, o_flags|O_DIRECT)) >= 0) {
577 (void)posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
578 close(fd);
579 }
580 }
581#endif
582 node->status = T_FINISHED;
583 bootlog(B_NOTICE, "service %s done", node->name);
584}
585
586
587/*
588 * Print out the status that bash can run eval.
589 * The following things will be printed:
590 * failed services, skipped services and the current progress value.
591 */
592void print_run_result(int *resvec, struct makenode **nodevec, const char *action)
593{
594 int i, r, stop = (! strcmp(action, "stop"));
595
596 printf("failed_service=\"");
597 i = r = 0;
598 for (i = 0; i < tree_entries; i++) {
599#if DEBUG
600 if (resvec[i] == 255) {
601 fprintf(stderr, "ERROR: forgotten process??\n");
602 exit(1);
603 }
604#endif
605 if (resvec[i] >= 1 && resvec[i] <= 4) {
606 if (r)
607 printf(" ");
608 printf("%s", nodevec[i]->name);
609 r++;
610 } else if (!stop && resvec[i] == 7) {
611 if (r)
612 printf(" ");
613 printf("%s", nodevec[i]->name);
614 r++;
615 }
616 }
617 printf("\"\n");
618 printf("skipped_service_not_installed=\"");
619 i = r = 0;
620 for (i = 0; i < tree_entries; i++) {
621 if (resvec[i] == 5) {
622 if (r)
623 printf(" ");
624 printf("%s", nodevec[i]->name);
625 r++;
626 }
627 }
628 printf("\"\n");
629 printf("skipped_service_not_configured=\"");
630 i = r = 0;
631 for (i = 0; i < tree_entries; i++) {
632 if (resvec[i] == 6) {
633 if (r)
634 printf(" ");
635 printf("%s", nodevec[i]->name);
636 r++;
637 }
638 }
639 printf("\"\n");
640}
641
642#if DEBUG
643void dump_status(void)
644{
645 struct makenode *node;
646
647 for (node = tree_list; node; node = node->next)
648 fprintf(stderr, "XXX %s: status = %d, dep = %d, int = %d, imp = %d\n",
649 node->name, node->status, node->num_deps, node->interactive, node->importance);
650}
651#endif
652
653#ifdef TEST
654void *xcalloc(size_t nmemb, size_t size)
655{
656 void *r;
657 if ((r = (void *)calloc(nmemb, size)) == 0) {
658 fprintf(stderr, "calloc: out of memory\n");
659 exit(1);
660 }
661 return r;
662}
663
664int main(int argc, char **argv)
665{
666 struct makenode *nodevec;
667 char makefile[64];
668
669 if (argc != 4) {
670 fprintf(stderr, "usage: makeboot <action> [<prev> <run>]\n");
671 goto out;
672 }
673
674 snprintf(makefile, sizeof(makefile), "depend.%s", argv[1]);
675 parse_makefile(makefile);
676
677 fprintf(stderr, "check_run_files(%s, %s, %s)\n", argv[1], argv[2],
678 argv[3]);
679 check_run_files(argv[1], argv[2], argv[3]);
680out:
681 while ((nodevec = pickup_task())) {
682 fprintf(stdout, "%s (%s)\n", nodevec->name, nodevec->arg0);
683 finish_task(nodevec);
684 }
685
686 return 0;
687}
688#endif
0689
=== modified file 'debian/changelog'
--- debian/changelog 2014-05-30 11:44:23 +0000
+++ debian/changelog 2014-06-05 13:25:18 +0000
@@ -1,3 +1,4 @@
1<<<<<<< TREE
1sysvinit (2.88dsf-41ubuntu16) utopic; urgency=medium2sysvinit (2.88dsf-41ubuntu16) utopic; urgency=medium
23
3 * Move sourcing of lsb/init-functions above the sourcing of helpers which we4 * Move sourcing of lsb/init-functions above the sourcing of helpers which we
@@ -6,6 +7,15 @@
67
7 -- Martin Pitt <martin.pitt@ubuntu.com> Fri, 30 May 2014 11:44:23 +02008 -- Martin Pitt <martin.pitt@ubuntu.com> Fri, 30 May 2014 11:44:23 +0200
89
10=======
11sysvinit (2.88dsf-41ubuntu16) UNRELEASED; urgency=medium
12
13 * Add 'task' knowledge to startpar.
14 * Re-enable startpar.
15
16 -- Dimitri John Ledkov <xnox@ubuntu.com> Fri, 30 May 2014 08:24:42 +0100
17
18>>>>>>> MERGE-SOURCE
9sysvinit (2.88dsf-41ubuntu15) utopic; urgency=medium19sysvinit (2.88dsf-41ubuntu15) utopic; urgency=medium
1020
11 * Disable startpar. It wreaks havoc with "task" upstart jobs as init.d21 * Disable startpar. It wreaks havoc with "task" upstart jobs as init.d
1222
=== modified file 'debian/patches/series'
--- debian/patches/series 2013-05-17 06:03:10 +0000
+++ debian/patches/series 2014-06-05 13:25:18 +0000
@@ -23,3 +23,4 @@
2393_run_initctl.patch2393_run_initctl.patch
2494_kfreebsd_xterm.patch2494_kfreebsd_xterm.patch
25upstart_support.patch25upstart_support.patch
26startpar-upstart-tasks.patch
2627
=== added file 'debian/patches/startpar-upstart-tasks.patch'
--- debian/patches/startpar-upstart-tasks.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/startpar-upstart-tasks.patch 2014-06-05 13:25:18 +0000
@@ -0,0 +1,28 @@
1Description: Add 'task' knowledge to startpar.
2Author: Dimitri John Ledkov <xnox@ubuntu.com>
3
4--- a/startpar/makeboot.c
5+++ b/startpar/makeboot.c
6@@ -445,12 +445,21 @@
7 asprintf(&command,
8 "/sbin/initctl status %s | grep -q start/running",
9 t->name);
10+ ret = system(command);
11+ if (WEXITSTATUS(ret) != 0) {
12+ free(command);
13+ asprintf(&command,
14+ "grep -q '^[ \t]*task[ \t]*$' %s",
15+ path);
16+ ret = system(command);
17+ }
18+
19 } else {
20 asprintf(&command,
21 "/sbin/initctl status %s | grep -q stop/waiting",
22 t->name);
23+ ret = system(command);
24 }
25- ret = system(command);
26 if (WEXITSTATUS(ret) == 0) {
27 nodevec[count] = t;
28 finish_task(t);
029
=== modified file 'debian/src/sysv-rc/etc/init.d/rc'
--- debian/src/sysv-rc/etc/init.d/rc 2014-05-29 10:15:57 +0000
+++ debian/src/sysv-rc/etc/init.d/rc 2014-06-05 13:25:18 +0000
@@ -69,9 +69,7 @@
69# insserv package to be enabled. Boot concurrency also requires69# insserv package to be enabled. Boot concurrency also requires
70# startpar to be installed.70# startpar to be installed.
71#71#
72#CONCURRENCY=makefile72CONCURRENCY=makefile
73# disable startpar, incompatible with "task" upstart jobs
74CONCURRENCY=none
75test -s /etc/init.d/.depend.boot || CONCURRENCY="none"73test -s /etc/init.d/.depend.boot || CONCURRENCY="none"
76test -s /etc/init.d/.depend.start || CONCURRENCY="none"74test -s /etc/init.d/.depend.start || CONCURRENCY="none"
77test -s /etc/init.d/.depend.stop || CONCURRENCY="none"75test -s /etc/init.d/.depend.stop || CONCURRENCY="none"
7876
=== modified file 'startpar/makeboot.c'
--- startpar/makeboot.c 2012-06-27 23:00:45 +0000
+++ startpar/makeboot.c 2014-06-05 13:25:18 +0000
@@ -445,12 +445,21 @@
445 asprintf(&command,445 asprintf(&command,
446 "/sbin/initctl status %s | grep -q start/running",446 "/sbin/initctl status %s | grep -q start/running",
447 t->name);447 t->name);
448 ret = system(command);
449 if (WEXITSTATUS(ret) != 0) {
450 free(command);
451 asprintf(&command,
452 "grep -q '^[ \t]*task[ \t]*$' %s",
453 path);
454 ret = system(command);
455 }
456
448 } else {457 } else {
449 asprintf(&command,458 asprintf(&command,
450 "/sbin/initctl status %s | grep -q stop/waiting",459 "/sbin/initctl status %s | grep -q stop/waiting",
451 t->name);460 t->name);
461 ret = system(command);
452 }462 }
453 ret = system(command);
454 if (WEXITSTATUS(ret) == 0) {463 if (WEXITSTATUS(ret) == 0) {
455 nodevec[count] = t;464 nodevec[count] = t;
456 finish_task(t);465 finish_task(t);

Subscribers

People subscribed via source and target branches