Dimitri John Ledkov has proposed merging
lp:~jamesodhunt/upstart/add-race-checking-tests into lp:upstart.
Requested reviews:
Upstart Reviewers (upstart-reviewers)
For more details, see:
https://code.launchpad.net/~jamesodhunt/upstart/add-race-checking-tests/+merge/225963
--
https://code.launchpad.net/~jamesodhunt/upstart/add-race-checking-tests/+merge/225963
Your team Upstart Reviewers is requested to review the proposed merge of
lp:~jamesodhunt/upstart/add-race-checking-tests into lp:upstart.
=== modified file 'init/job_process.c'
--- init/job_process.c 2014-07-03 08:59:30 +0000
+++ init/job_process.c 2014-07-08 12:43:53 +0000
@@ -111,9 +111,6 @@
int disable_respawn = FALSE;
/* Prototypes for static functions */
-static void job_process_error_abort (int fd, JobProcessErrorType type,
- int arg)
- __attribute__ ((noreturn));
static void job_process_remap_fd (int *fd, int reserved_fd, int error_fd);
/**
@@ -983,7 +980,7 @@
*
* This function calls the exit() system call, so never returns.
**/
-static void
+void
job_process_error_abort (int fd,
JobProcessErrorType type,
int arg)
=== modified file 'init/job_process.h'
--- init/job_process.h 2014-06-02 20:29:33 +0000
+++ init/job_process.h 2014-07-08 12:43:53 +0000
@@ -194,6 +194,10 @@
void job_process_error_handler (const char *buf, size_t len);
+void job_process_error_abort (int fd, JobProcessErrorType type,
+ int arg)
+ __attribute__ ((noreturn));
+
NIH_END_EXTERN
#endif /* INIT_JOB_PROCESS_H */
=== modified file 'init/tests/test_job_process.c'
--- init/tests/test_job_process.c 2014-07-07 10:15:25 +0000
+++ init/tests/test_job_process.c 2014-07-08 12:43:53 +0000
@@ -5486,8 +5486,13 @@
unsigned long data;
struct timespec now;
char dirname[PATH_MAX];
+<<<<<<< TREE
nih_local char *logfile = NULL;
int fds[2] = { -1, -1};
+=======
+ int fds[2] = { -1, -1};
+ NihIo *io = NULL;
+>>>>>>> MERGE-SOURCE
TEST_FILENAME (dirname);
TEST_EQ (mkdir (dirname, 0755), 0);
@@ -8770,13 +8775,252 @@
fclose (output);
+ nih_free (event);
+ event_poll ();
+
+ TEST_RESET_MAIN_LOOP ();
+
+ /************************************************************/
+ /* Ensure that if a child is setup successfully and then exits
+ * before the main loop detects the child fd has closed (due to
+ * the child calling execvp()), that the state is correct.
+ */
+ TEST_FEATURE ("with child exit notification before child setup success notification");
+
+ job = job_new (class, "");
+ TEST_NE_P (job, NULL);
+
+ job->goal = JOB_START;
+ job->state = JOB_SPAWNING;
+
+ assert0 (pipe (fds));
+
+ job->process_data[PROCESS_MAIN] = job_process_data_new (job->process_data,
+ job, PROCESS_MAIN, fds[0]);
+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
+
+ TEST_NE_P (class->process[PROCESS_MAIN], NULL);
+ TEST_EQ_P (class->process[PROCESS_PRE_START], NULL);
+ TEST_EQ_P (class->process[PROCESS_POST_START], NULL);
+ TEST_EQ_P (class->process[PROCESS_PRE_STOP], NULL);
+ TEST_EQ_P (class->process[PROCESS_POST_STOP], NULL);
+ TEST_EQ_P (class->process[PROCESS_SECURITY], NULL);
+
+ TEST_CHILD (job->pid[PROCESS_MAIN]) {
+ close (fds[0]);
+
+ nih_io_set_cloexec (fds[1]);
+
+ execl ("/bin/true", "/bin/true", NULL);
+ }
+ close (fds[1]);
+
+ TEST_FREE_TAG (job);
+
+ job_process_handler (NULL, job->pid[PROCESS_MAIN],
+ NIH_CHILD_EXITED, 0);
+
+ TEST_NOT_FREE (job);
+
+ /* goal should not change until the IO handlers have had a
+ * chance to run.
+ */
+ TEST_EQ (job->goal, JOB_START);
+
+ TEST_EQ (job->state, JOB_SPAWNED);
+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
+
+ TEST_TRUE (job->process_data[PROCESS_MAIN]->valid);
+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, fds[0]);
+ TEST_EQ (job->process_data[PROCESS_MAIN]->shell_fd, -1);
+ TEST_EQ_P (job->process_data[PROCESS_MAIN]->script, NULL);
+ TEST_EQ (job->process_data[PROCESS_MAIN]->status, 0);
+
+ close (fds[0]);
+ nih_free (job);
+
+ TEST_RESET_MAIN_LOOP ();
+
+ /************************************************************/
+ /* Ensure that if a child failed to be setup and then exits
+ * before the main loop detects the child fd has data to read
+ * that the state is correct.
+ */
+ TEST_FEATURE ("with child exit notification before child setup failure notification");
+
+ job = job_new (class, "");
+ TEST_NE_P (job, NULL);
+
+ job->goal = JOB_START;
+ job->state = JOB_SPAWNING;
+
+ assert0 (pipe (fds));
+
+ job->process_data[PROCESS_MAIN] = job_process_data_new (job->process_data,
+ job, PROCESS_MAIN, fds[0]);
+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, fds[0]);
+ TEST_EQ (job->process_data[PROCESS_MAIN]->process, PROCESS_MAIN);
+
+ TEST_CHILD (job->pid[PROCESS_MAIN]) {
+ close (fds[0]);
+
+ nih_error_raise_no_memory ();
+ job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CGROUP_SETUP, 0);
+ }
+ close (fds[1]);
+
+ TEST_FREE_TAG (job);
+
+ job_process_handler (NULL, job->pid[PROCESS_MAIN],
+ NIH_CHILD_DUMPED, SIGABRT);
+
+ TEST_NOT_FREE (job);
+
+ /* goal should not change until the IO handlers have had a
+ * chance to run.
+ */
+ TEST_EQ (job->goal, JOB_START);
+
+ TEST_EQ (job->state, JOB_SPAWNED);
+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
+
+ /* Still valid because the IO handlers haven't fired yet */
+ TEST_TRUE (job->process_data[PROCESS_MAIN]->valid);
+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, fds[0]);
+
+ TEST_EQ (job->process_data[PROCESS_MAIN]->shell_fd, -1);
+ TEST_EQ_P (job->process_data[PROCESS_MAIN]->script, NULL);
+ TEST_NE (job->process_data[PROCESS_MAIN]->status, 0);
+
+ close (fds[0]);
+ nih_free (job);
+
+ TEST_RESET_MAIN_LOOP ();
+
+ /************************************************************/
+ TEST_FEATURE ("with child setup success notification before child exit notification");
+
+ job = job_new (class, "");
+ TEST_NE_P (job, NULL);
+
+ job->goal = JOB_START;
+ job->state = JOB_SPAWNING;
+
+ assert0 (pipe (fds));
+
+ job->process_data[PROCESS_MAIN] = job_process_data_new (job->process_data,
+ job, PROCESS_MAIN, fds[0]);
+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, fds[0]);
+ TEST_EQ (job->process_data[PROCESS_MAIN]->process, PROCESS_MAIN);
+
+ io = nih_io_reopen (job->process_data[PROCESS_MAIN],
+ fds[0],
+ NIH_IO_STREAM,
+ (NihIoReader)job_process_child_reader,
+ (NihIoCloseHandler)job_process_close_handler,
+ NULL,
+ job->process_data[PROCESS_MAIN]);
+ TEST_NE_P (io, NULL);
+
+ TEST_CHILD (job->pid[PROCESS_MAIN]) {
+ close (fds[0]);
+
+ nih_io_set_cloexec (fds[1]);
+
+ execl ("/bin/true", "/bin/true", NULL);
+ }
+ close (fds[1]);
+
+ job_process_close_handler (job->process_data[PROCESS_MAIN], io);
+
+ TEST_EQ (job->goal, JOB_START);
+ TEST_EQ (job->state, JOB_SPAWNED);
+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
+
+ /* Invalid because the IO handlers have now run */
+ TEST_FALSE (job->process_data[PROCESS_MAIN]->valid);
+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, -1);
+
+ TEST_EQ (job->process_data[PROCESS_MAIN]->shell_fd, -1);
+ TEST_EQ_P (job->process_data[PROCESS_MAIN]->script, NULL);
+ TEST_EQ (job->process_data[PROCESS_MAIN]->status, 0);
+
+ close (fds[0]);
+ nih_free (job);
+
+ TEST_RESET_MAIN_LOOP ();
+
+ /************************************************************/
+ TEST_FEATURE ("with child setup failure notification before child exit notification");
+
+ job = job_new (class, "");
+ TEST_NE_P (job, NULL);
+
+ job->goal = JOB_START;
+ job->state = JOB_SPAWNING;
+
+ assert0 (pipe (fds));
+
+ job->process_data[PROCESS_MAIN] = job_process_data_new (job->process_data,
+ job, PROCESS_MAIN, fds[0]);
+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, fds[0]);
+ TEST_EQ (job->process_data[PROCESS_MAIN]->process, PROCESS_MAIN);
+
+ /* Can't use job_register_child_handler() as we want the return
+ * value.
+ */
+ io = nih_io_reopen (job->process_data[PROCESS_MAIN],
+ fds[0],
+ NIH_IO_STREAM,
+ (NihIoReader)job_process_child_reader,
+ (NihIoCloseHandler)job_process_close_handler,
+ NULL,
+ job->process_data[PROCESS_MAIN]);
+ TEST_NE_P (io, NULL);
+
+ TEST_CHILD (job->pid[PROCESS_MAIN]) {
+ close (fds[0]);
+
+ nih_error_raise_no_memory ();
+ job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CGROUP_SETUP, 0);
+ }
+ close (fds[1]);
+
+ job_process_close_handler (job->process_data[PROCESS_MAIN], io);
+
+ TEST_EQ (job->goal, JOB_START);
+ TEST_EQ (job->state, JOB_SPAWNED);
+ TEST_NE_P (job->process_data[PROCESS_MAIN], NULL);
+
+ /* Invalid because the IO handlers have now run */
+ TEST_FALSE (job->process_data[PROCESS_MAIN]->valid);
+ TEST_EQ (job->process_data[PROCESS_MAIN]->job_process_fd, -1);
+
+ TEST_EQ (job->process_data[PROCESS_MAIN]->shell_fd, -1);
+ TEST_EQ_P (job->process_data[PROCESS_MAIN]->script, NULL);
+ TEST_EQ (job->process_data[PROCESS_MAIN]->shell_fd, -1);
+
+ /* Still zero because the process handler hasn't run yet */
+ TEST_EQ (job->process_data[PROCESS_MAIN]->status, 0);
+
+ waitpid (job->pid[PROCESS_MAIN], &status, 0);
+
+ /* Only now can we close the pipe */
+ close (fds[0]);
+
+ nih_free (job);
+
+ TEST_RESET_MAIN_LOOP ();
+
+ /************************************************************/
+
nih_free (class);
file->job = NULL;
nih_free (source);
- nih_free (event);
- event_poll ();
-
TEST_EQ (rmdir (dirname), 0);
TEST_EQ (unsetenv ("UPSTART_LOGDIR"), 0);
}
@@ -9153,13 +9397,17 @@
void
run_tests (void)
{
+#if 0
test_start ();
test_spawn ();
test_log_path ();
test_kill ();
+#endif
test_handler ();
+#if 0
test_utmp ();
test_find ();
+#endif
}
/**
--
upstart-devel mailing list
[email protected]
Modify settings or unsubscribe at:
https://lists.ubuntu.com/mailman/listinfo/upstart-devel