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 upstart-devel@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/upstart-devel