Merge lp:~stgraber/upstart/upstart-fix-respawn into lp:upstart

Proposed by Stéphane Graber
Status: Merged
Merged at revision: 1498
Proposed branch: lp:~stgraber/upstart/upstart-fix-respawn
Merge into: lp:upstart
Diff against target: 143 lines (+21/-10)
2 files modified
init/job_process.c (+0/-6)
init/tests/test_job_process.c (+21/-4)
To merge this branch: bzr merge lp:~stgraber/upstart/upstart-fix-respawn
Reviewer Review Type Date Requested Status
Steve Langasek Needs Fixing
Review via email: mp+172420@code.launchpad.net

Description of the change

This fixes a regression recently found when working on Ubuntu Touch.

The problem is that if a job has the respawn flag and doesn't contain any of the standard shell characters in its exec line, upstart will still set job->script to TRUE once the initial run has succeeded. This mean that on first respawn of the job, it'll end up forking one extra time and confuse upstart.

The change that introduced this was done to fix a case where tests would fail when running from a directory containing a shell character in its name (~test for example). The assumption at the time being that ->script wasn't persistent (clearly wrong) and that it wouldn't hurt to set it after the job has been started in order to simplify testing.

The fix is to revert the change to upstart itself and instead include the same shell characters list in the testsuite and have the testsuite check against it just like init itself does.

To post a comment you must log in.
Revision history for this message
Steve Langasek (vorlon) wrote :

As discussed on IRC, this change should include an affirmative test case to ensure the correct values of ->script on respawn, to avoid this bug being reintroduced later.

review: Needs Fixing
1499. By Stéphane Graber

Add some tests

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

Locally applying the changes to init/tests/test_job_process.c without the changes to the code, the test suite still passes; so the added test case clearly doesn't actually check for the bug in question and avoid regressing this particular code path.

Needs a test case involving a job with both an exec line and shell chars.

review: Needs Fixing
1500. By Stéphane Graber

Add check for ->script value when the exec line contains shell characters in one of the command arguments.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'init/job_process.c'
--- init/job_process.c 2013-05-31 15:34:00 +0000
+++ init/job_process.c 2013-07-01 23:24:24 +0000
@@ -261,12 +261,6 @@
261 NIH_MUST (nih_str_array_addp (&argv, NULL,261 NIH_MUST (nih_str_array_addp (&argv, NULL,
262 &argc, cmd));262 &argc, cmd));
263 }263 }
264
265 /* At the end, always set proc->script to TRUE, even if the user didn't
266 * explicitly set it (when using shell variables). That way tests
267 * can reliably check for shell-specific behaviour.
268 */
269 proc->script = TRUE;
270 } else {264 } else {
271 /* Split the command on whitespace to produce a list of265 /* Split the command on whitespace to produce a list of
272 * arguments that we can exec directly.266 * arguments that we can exec directly.
273267
=== modified file 'init/tests/test_job_process.c'
--- init/tests/test_job_process.c 2013-06-25 09:19:05 +0000
+++ init/tests/test_job_process.c 2013-07-01 23:24:24 +0000
@@ -83,6 +83,14 @@
83#define MAX_ITERATIONS 583#define MAX_ITERATIONS 5
8484
85/**85/**
86 * SHELL_CHARS:
87 *
88 * This is the list of characters that, if encountered in a process, cause
89 * it to always be run with a shell.
90 **/
91#define SHELL_CHARS "~`!$^&*()=|\\{}[];\"'<>?"
92
93/**
86 * CHECK_FILE_EQ:94 * CHECK_FILE_EQ:
87 *95 *
88 * @_file: FILE to read from,96 * @_file: FILE to read from,
@@ -501,6 +509,7 @@
501509
502 waitpid (job->pid[PROCESS_MAIN], NULL, 0);510 waitpid (job->pid[PROCESS_MAIN], NULL, 0);
503 TEST_EQ (stat (filename, &statbuf), 0);511 TEST_EQ (stat (filename, &statbuf), 0);
512 TEST_EQ (job->class->process[PROCESS_MAIN]->script, FALSE);
504513
505 /* Filename should contain the pid */514 /* Filename should contain the pid */
506 output = fopen (filename, "r");515 output = fopen (filename, "r");
@@ -677,7 +686,7 @@
677 output = fopen (filename, "r");686 output = fopen (filename, "r");
678 TEST_FILE_EQ (output, "BAR=BAZ\n");687 TEST_FILE_EQ (output, "BAR=BAZ\n");
679 TEST_FILE_EQ (output, "FOO=BAR\n");688 TEST_FILE_EQ (output, "FOO=BAR\n");
680 if (job->class->process[PROCESS_MAIN]->script)689 if (job->class->process[PROCESS_MAIN]->script || strpbrk (job->class->process[PROCESS_MAIN]->command, SHELL_CHARS))
681 TEST_FILE_EQ (output, "PWD=/\n");690 TEST_FILE_EQ (output, "PWD=/\n");
682 TEST_FILE_EQ (output, "UPSTART_INSTANCE=\n");691 TEST_FILE_EQ (output, "UPSTART_INSTANCE=\n");
683 TEST_FILE_EQ (output, "UPSTART_JOB=test\n");692 TEST_FILE_EQ (output, "UPSTART_JOB=test\n");
@@ -733,7 +742,7 @@
733 output = fopen (filename, "r");742 output = fopen (filename, "r");
734 TEST_FILE_EQ (output, "BAR=BAZ\n");743 TEST_FILE_EQ (output, "BAR=BAZ\n");
735 TEST_FILE_EQ (output, "FOO=BAR\n");744 TEST_FILE_EQ (output, "FOO=BAR\n");
736 if (job->class->process[PROCESS_MAIN]->script)745 if (job->class->process[PROCESS_MAIN]->script || strpbrk (job->class->process[PROCESS_MAIN]->command, SHELL_CHARS))
737 TEST_FILE_EQ (output, "PWD=/\n");746 TEST_FILE_EQ (output, "PWD=/\n");
738 TEST_FILE_EQ (output, "UPSTART_INSTANCE=foo\n");747 TEST_FILE_EQ (output, "UPSTART_INSTANCE=foo\n");
739 TEST_FILE_EQ (output, "UPSTART_JOB=test\n");748 TEST_FILE_EQ (output, "UPSTART_JOB=test\n");
@@ -791,7 +800,7 @@
791 TEST_FILE_EQ (output, "BAR=BAZ\n");800 TEST_FILE_EQ (output, "BAR=BAZ\n");
792 TEST_FILE_EQ (output, "CRACKLE=FIZZ\n");801 TEST_FILE_EQ (output, "CRACKLE=FIZZ\n");
793 TEST_FILE_EQ (output, "FOO=SMACK\n");802 TEST_FILE_EQ (output, "FOO=SMACK\n");
794 if (job->class->process[PROCESS_PRE_STOP]->script)803 if (job->class->process[PROCESS_PRE_STOP]->script || strpbrk (job->class->process[PROCESS_PRE_STOP]->command, SHELL_CHARS))
795 TEST_FILE_EQ (output, "PWD=/\n");804 TEST_FILE_EQ (output, "PWD=/\n");
796 TEST_FILE_EQ (output, "UPSTART_INSTANCE=\n");805 TEST_FILE_EQ (output, "UPSTART_INSTANCE=\n");
797 TEST_FILE_EQ (output, "UPSTART_JOB=test\n");806 TEST_FILE_EQ (output, "UPSTART_JOB=test\n");
@@ -849,7 +858,7 @@
849 TEST_FILE_EQ (output, "BAR=BAZ\n");858 TEST_FILE_EQ (output, "BAR=BAZ\n");
850 TEST_FILE_EQ (output, "CRACKLE=FIZZ\n");859 TEST_FILE_EQ (output, "CRACKLE=FIZZ\n");
851 TEST_FILE_EQ (output, "FOO=SMACK\n");860 TEST_FILE_EQ (output, "FOO=SMACK\n");
852 if (job->class->process[PROCESS_POST_STOP]->script)861 if (job->class->process[PROCESS_POST_STOP]->script || strpbrk (job->class->process[PROCESS_POST_STOP]->command, SHELL_CHARS))
853 TEST_FILE_EQ (output, "PWD=/\n");862 TEST_FILE_EQ (output, "PWD=/\n");
854 TEST_FILE_EQ (output, "UPSTART_INSTANCE=\n");863 TEST_FILE_EQ (output, "UPSTART_INSTANCE=\n");
855 TEST_FILE_EQ (output, "UPSTART_JOB=test\n");864 TEST_FILE_EQ (output, "UPSTART_JOB=test\n");
@@ -6069,6 +6078,7 @@
6069 TEST_EQ (job->failed, FALSE);6078 TEST_EQ (job->failed, FALSE);
6070 TEST_EQ (job->failed_process, PROCESS_INVALID);6079 TEST_EQ (job->failed_process, PROCESS_INVALID);
6071 TEST_EQ (job->exit_status, 0);6080 TEST_EQ (job->exit_status, 0);
6081 TEST_EQ (job->class->process[PROCESS_MAIN]->script, FALSE);
60726082
6073 TEST_FILE_EQ (output, ("test: test main process (1) "6083 TEST_FILE_EQ (output, ("test: test main process (1) "
6074 "terminated with status 1\n"));6084 "terminated with status 1\n"));
@@ -6156,6 +6166,7 @@
6156 TEST_EQ (job->failed, FALSE);6166 TEST_EQ (job->failed, FALSE);
6157 TEST_EQ (job->failed_process, PROCESS_INVALID);6167 TEST_EQ (job->failed_process, PROCESS_INVALID);
6158 TEST_EQ (job->exit_status, 0);6168 TEST_EQ (job->exit_status, 0);
6169 TEST_EQ (job->class->process[PROCESS_MAIN]->script, FALSE);
61596170
6160 TEST_FILE_EQ (output, ("test: test main process (1) "6171 TEST_FILE_EQ (output, ("test: test main process (1) "
6161 "terminated with status 1\n"));6172 "terminated with status 1\n"));
@@ -6240,6 +6251,7 @@
6240 TEST_EQ (job->failed, TRUE);6251 TEST_EQ (job->failed, TRUE);
6241 TEST_EQ (job->failed_process, PROCESS_INVALID);6252 TEST_EQ (job->failed_process, PROCESS_INVALID);
6242 TEST_EQ (job->exit_status, 0);6253 TEST_EQ (job->exit_status, 0);
6254 TEST_EQ (job->class->process[PROCESS_MAIN]->script, FALSE);
62436255
6244 TEST_FILE_EQ (output, ("test: test respawning too fast, "6256 TEST_FILE_EQ (output, ("test: test respawning too fast, "
6245 "stopped\n"));6257 "stopped\n"));
@@ -6313,6 +6325,7 @@
6313 TEST_EQ (job->failed, FALSE);6325 TEST_EQ (job->failed, FALSE);
6314 TEST_EQ (job->failed_process, PROCESS_INVALID);6326 TEST_EQ (job->failed_process, PROCESS_INVALID);
6315 TEST_EQ (job->exit_status, 0);6327 TEST_EQ (job->exit_status, 0);
6328 TEST_EQ (job->class->process[PROCESS_MAIN]->script, FALSE);
63166329
6317 nih_free (job);6330 nih_free (job);
6318 }6331 }
@@ -6390,6 +6403,7 @@
6390 TEST_EQ (job->failed, FALSE);6403 TEST_EQ (job->failed, FALSE);
6391 TEST_EQ (job->failed_process, PROCESS_INVALID);6404 TEST_EQ (job->failed_process, PROCESS_INVALID);
6392 TEST_EQ (job->exit_status, 0);6405 TEST_EQ (job->exit_status, 0);
6406 TEST_EQ (job->class->process[PROCESS_MAIN]->script, FALSE);
63936407
6394 TEST_FILE_EQ (output, ("test: test main process ended, "6408 TEST_FILE_EQ (output, ("test: test main process ended, "
6395 "respawning\n"));6409 "respawning\n"));
@@ -6462,6 +6476,7 @@
6462 TEST_EQ (job->failed, FALSE);6476 TEST_EQ (job->failed, FALSE);
6463 TEST_EQ (job->failed_process, PROCESS_INVALID);6477 TEST_EQ (job->failed_process, PROCESS_INVALID);
6464 TEST_EQ (job->exit_status, 0);6478 TEST_EQ (job->exit_status, 0);
6479 TEST_EQ (job->class->process[PROCESS_MAIN]->script, FALSE);
64656480
6466 nih_free (job);6481 nih_free (job);
6467 }6482 }
@@ -7423,6 +7438,7 @@
7423 TEST_EQ (job->failed, FALSE);7438 TEST_EQ (job->failed, FALSE);
7424 TEST_EQ (job->failed_process, PROCESS_INVALID);7439 TEST_EQ (job->failed_process, PROCESS_INVALID);
7425 TEST_EQ (job->exit_status, 0);7440 TEST_EQ (job->exit_status, 0);
7441 TEST_EQ (job->class->process[PROCESS_MAIN]->script, FALSE);
74267442
7427 TEST_FILE_EQ (output, ("test: test main process ended, "7443 TEST_FILE_EQ (output, ("test: test main process ended, "
7428 "respawning\n"));7444 "respawning\n"));
@@ -7739,6 +7755,7 @@
7739 TEST_EQ (job->failed, FALSE);7755 TEST_EQ (job->failed, FALSE);
7740 TEST_EQ (job->failed_process, PROCESS_INVALID);7756 TEST_EQ (job->failed_process, PROCESS_INVALID);
7741 TEST_EQ (job->exit_status, 0);7757 TEST_EQ (job->exit_status, 0);
7758 TEST_EQ (job->class->process[PROCESS_MAIN]->script, FALSE);
77427759
7743 TEST_FILE_EQ (output, ("test: test main process ended, "7760 TEST_FILE_EQ (output, ("test: test main process ended, "
7744 "respawning\n"));7761 "respawning\n"));

Subscribers

People subscribed via source and target branches