upstart shell magic for exec line

Maxim Nikulin m.a.nikulin at gmail.com
Wed Jun 12 09:37:54 UTC 2013


Hi.

Debugging https://bugs.launchpad.net/bugs/1181789 I have traced that 
service may be launched with different argv array on first and later 
start invocations. The deep consequence is a log file open for writing 
when root filesystem must be remount readonly during shutdown.

Job .conf file (quotes around "exec" are crucial):

expect fork
exec /bin/sh -c "exit"

First 'initctl start' invocation, argv argument of 
init/job_process.c:job_process_spawn()

{0x809b730 "/bin/sh", 0x809e448 "-e", 0x809e758 "-c",
   0x809e4c8 "exec /bin/sh -c \"exit\"", 0x809b548 "/bin/sh"}

Second call:
{0x809b730 "/bin/sh", 0x809f0f8 "-e", 0x809e758 "-c",
   0x809e950 "/bin/sh -c \"exit\"", 0x809ef90 "/bin/sh"}

Note that exec is missed second time.

I think it is due to line 268 of init/job_process.c
>                 /* At the end, always set proc->script to TRUE, even if the user didn't
>                  * explicitly set it (when using shell variables). That way tests
>                  * can reliably check for shell-specific behaviour.
>                  */
>                 proc->script = TRUE;

As a result 'exec' is added only during the first start of service
(line 219):
>                 /* If the process wasn't originally marked to be run through
>                  * a shell, prepend exec to the script so that the shell
>                  * gets out of the way after parsing.
>                  */
>                 if (proc->script) {
>                         script = NIH_MUST (nih_strdup (NULL, proc->command));
>                 } else {
>                         script = NIH_MUST (nih_sprintf (NULL, "exec %s",
>                                                         proc->command));
>                 }

The result is the following process tree

> 20131 pts/1    S+     0:00  |       \_ gdb --args ./init --confdir /tmp/conf --logdir /tmp/log --no-sessions --session
> 20137 pts/1    t      0:00  |           \_ /home/u/src/ureadahead/upstart-1.8/init/init --confdir /tmp/conf --logdir /tmp/log --no-sessions --session
> 20635 ?        ts     0:00  |               \_ /bin/sh -e -c /bin/sh -c "exit" /bin/sh
> 20647 ?        t      0:00  |                   \_ /bin/sh -e -c /bin/sh -c "exit" /bin/sh

Upstart catches fork for the second shell and believes that the process 
is started. (Should not it notice that the new process exits immediately?)

Are there any side effects of removing the line 268?
	proc->script = TRUE;
(Besides test for shell characters on each start)

-- 
Maxim Nikulin



More information about the upstart-devel mailing list