[upstart/f13/master] upstart-utmp.patch - set DEAD_PROCESS for died process with pid in utmp table
Petr Lautrbach
plautrba at fedoraproject.org
Tue Sep 21 13:45:57 UTC 2010
commit db45477d6b5adb686163aba970ff8062f2801e98
Author: Petr Lautrbach <plautrba at redhat.com>
Date: Tue Sep 21 13:06:26 2010 +0200
upstart-utmp.patch - set DEAD_PROCESS for died process with pid in utmp table
upstart-utmp.patch | 317 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 317 insertions(+), 0 deletions(-)
---
diff --git a/upstart-utmp.patch b/upstart-utmp.patch
new file mode 100644
index 0000000..255bc50
--- /dev/null
+++ b/upstart-utmp.patch
@@ -0,0 +1,317 @@
+diff --git a/init/job_class.c b/init/job_class.c
+index b521cf4..1b8d1cf 100644
+--- a/init/job_class.c
++++ b/init/job_class.c
+@@ -218,6 +218,8 @@ job_class_new (const void *parent,
+ class->chroot = NULL;
+ class->chdir = NULL;
+
++ class->utmp_id = NULL;
++
+ class->deleted = FALSE;
+
+ return class;
+diff --git a/init/job_class.h b/init/job_class.h
+index b7d4eed..1d29c59 100644
+--- a/init/job_class.h
++++ b/init/job_class.h
+@@ -145,6 +145,7 @@ typedef struct job_class {
+ struct rlimit *limits[RLIMIT_NLIMITS];
+ char *chroot;
+ char *chdir;
++ char *utmp_id;
+
+ int deleted;
+ } JobClass;
+diff --git a/init/job_process.c b/init/job_process.c
+index e3080d8..8ce2f72 100644
+--- a/init/job_process.c
++++ b/init/job_process.c
+@@ -38,6 +38,8 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
++#include <utmp.h>
++#include <utmpx.h>
+
+ #include <nih/macros.h>
+ #include <nih/alloc.h>
+@@ -361,11 +363,13 @@ job_process_spawn (JobClass *class,
+ char * const *env,
+ int trace)
+ {
+- sigset_t child_set, orig_set;
+- pid_t pid;
+- int i, fds[2];
+- char filename[PATH_MAX];
+- FILE *fd;
++ sigset_t child_set, orig_set;
++ pid_t pid;
++ int i, fds[2];
++ char filename[PATH_MAX];
++ FILE *fd;
++ struct utmpx utmp;
++ struct timeval tv;
+
+ nih_assert (class != NULL);
+
+@@ -524,6 +528,20 @@ job_process_spawn (JobClass *class,
+ }
+ }
+
++ /* Write utmp INIT_PROCESS entry */
++ if (class->utmp_id) {
++ memset(&utmp, 0, sizeof(struct utmpx));
++ strncpy(utmp.ut_id, class->utmp_id, sizeof(utmp.ut_id));
++ utmp.ut_pid = getpid();
++ utmp.ut_type = INIT_PROCESS;
++ gettimeofday(&tv, NULL);
++ utmp.ut_tv.tv_sec = tv.tv_sec;
++ utmp.ut_tv.tv_usec = tv.tv_usec;
++ setutxent();
++ pututxline(&utmp);
++ endutxent();
++ }
++
+ /* Execute the process, if we escape from here it failed */
+ if (execvp (argv[0], argv) < 0) {
+ nih_error_raise_system ();
+@@ -967,6 +985,8 @@ job_process_terminated (Job *job,
+ int status)
+ {
+ int failed = FALSE, stop = FALSE, state = TRUE;
++ struct utmpx *utmptr;
++ struct timeval tv;
+
+ nih_assert (job != NULL);
+
+@@ -1129,6 +1149,36 @@ job_process_terminated (Job *job,
+ job->kill_process = -1;
+ }
+
++ /* Find existing utmp entry for the process pid */
++ setutxent();
++ while ((utmptr = getutxent()) != NULL) {
++ if (utmptr->ut_pid == job->pid[process]) {
++ /* set type and clean ut_user, ut_host,
++ * ut_time as described in utmp(5)
++ */
++ utmptr->ut_type = DEAD_PROCESS;
++ memset(utmptr->ut_user, 0, UT_NAMESIZE);
++ memset(utmptr->ut_host, 0, UT_HOSTSIZE);
++ utmptr->ut_time = 0;
++
++ /* Set class utmp_id for next spawn */
++ job->class->utmp_id = nih_strdup (job->class, utmptr->ut_id);
++
++ /* Update existing utmp file. */
++ pututxline(utmptr);
++
++ /* set ut_time for log */
++ gettimeofday(&tv, NULL);
++ utmptr->ut_tv.tv_sec = tv.tv_sec;
++ utmptr->ut_tv.tv_usec = tv.tv_usec;
++ /* Write wtmp entry */
++ updwtmpx (_PATH_WTMP, utmptr);
++
++ break;
++ }
++ }
++ endutxent();
++
+ /* Clear the process pid field */
+ job->pid[process] = 0;
+
+diff --git a/init/tests/test_job_process.c b/init/tests/test_job_process.c
+index d43fa6e..b4f94e4 100644
+--- a/init/tests/test_job_process.c
++++ b/init/tests/test_job_process.c
+@@ -36,6 +36,8 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
++#include <utmp.h>
++#include <utmpx.h>
+
+ #include <nih/macros.h>
+ #include <nih/string.h>
+@@ -4474,6 +4476,171 @@ test_find (void)
+ }
+
+
++void
++test_utmp (void)
++{
++ JobClass * class;
++ Job * job = NULL;
++ Blocked * blocked = NULL;
++ Event * event;
++ FILE * output;
++ char utmpname[PATH_MAX];
++ struct utmpx utmp, *utmptr;
++ struct timeval tv;
++
++ TEST_FUNCTION ("job_process_handler");
++ program_name = "test";
++
++ class = job_class_new (NULL, "test");
++ class->process[PROCESS_MAIN] = process_new (class);
++ class->process[PROCESS_MAIN]->command = "echo";
++
++ class->start_on = event_operator_new (class, EVENT_MATCH,
++ "foo", NULL);
++ class->stop_on = event_operator_new (class, EVENT_MATCH,
++ "foo", NULL);
++ nih_hash_add (job_classes, &class->entry);
++
++ event = event_new (NULL, "foo", NULL);
++
++ TEST_FILENAME(utmpname);
++
++ /* Check that utmp record for the running task of the job terminating
++ * is properly changed to DEAD_PROCESS
++ */
++ TEST_FEATURE ("with LOGIN_PROCESS utmp entry");
++ TEST_ALLOC_FAIL {
++ TEST_ALLOC_SAFE {
++ job = job_new (class, "");
++
++ blocked = blocked_new (job, BLOCKED_EVENT, event);
++ event_block (event);
++ nih_list_add (&job->blocking, &blocked->entry);
++ }
++
++ job->goal = JOB_START;
++ job->state = JOB_RUNNING;
++ job->pid[PROCESS_MAIN] = 1;
++
++ TEST_FREE_TAG (blocked);
++
++ job->blocker = NULL;
++ event->failed = FALSE;
++
++ job->failed = FALSE;
++ job->failed_process = -1;
++ job->exit_status = 0;
++
++ output = fopen (utmpname, "w");
++ fclose (output);
++
++ /* set utmp file */
++ utmpxname(utmpname);
++
++ /* set up utmp entries */
++ memset (&utmp, 0, sizeof utmp);
++
++ strcpy(utmp.ut_id, "2");
++ utmp.ut_type = LOGIN_PROCESS;
++ utmp.ut_pid = 2;
++
++ gettimeofday(&tv, NULL);
++ utmp.ut_tv.tv_sec = tv.tv_sec;
++ utmp.ut_tv.tv_usec = tv.tv_usec;
++
++ setutxent();
++ pututxline(&utmp);
++
++ strcpy(utmp.ut_id, "1");
++ utmp.ut_pid = 1;
++ pututxline(&utmp);
++
++ endutxent();
++
++ job_process_handler (NULL, 1, NIH_CHILD_EXITED, 0);
++
++ setutxent();
++
++ utmptr = getutxent();
++ TEST_NE_P(utmptr, NULL);
++ TEST_EQ(utmptr->ut_pid, 2);
++ TEST_EQ(utmptr->ut_type, LOGIN_PROCESS);
++
++ utmptr = getutxent();
++ TEST_NE_P(utmptr, NULL);
++ TEST_EQ(utmptr->ut_pid, 1);
++ TEST_EQ(utmptr->ut_type, DEAD_PROCESS);
++
++ nih_free (job);
++ }
++ TEST_FEATURE ("with USER_PROCESS utmp entry");
++ TEST_ALLOC_FAIL {
++ TEST_ALLOC_SAFE {
++ job = job_new (class, "");
++
++ blocked = blocked_new (job, BLOCKED_EVENT, event);
++ event_block (event);
++ nih_list_add (&job->blocking, &blocked->entry);
++ }
++
++ job->goal = JOB_START;
++ job->state = JOB_RUNNING;
++ job->pid[PROCESS_MAIN] = 1;
++
++ TEST_FREE_TAG (blocked);
++
++ job->blocker = NULL;
++ event->failed = FALSE;
++
++ job->failed = FALSE;
++ job->failed_process = -1;
++ job->exit_status = 0;
++
++ output = fopen (utmpname, "w");
++ fclose (output);
++
++ /* set utmp file */
++ utmpxname(utmpname);
++
++ /* set up utmp entries */
++ memset (&utmp, 0, sizeof utmp);
++
++ strcpy(utmp.ut_id, "2");
++ utmp.ut_type = USER_PROCESS;
++ utmp.ut_pid = 2;
++
++ gettimeofday(&tv, NULL);
++ utmp.ut_tv.tv_sec = tv.tv_sec;
++ utmp.ut_tv.tv_usec = tv.tv_usec;
++
++ setutxent();
++ pututxline(&utmp);
++
++ strcpy(utmp.ut_id, "1");
++ utmp.ut_pid = 1;
++ pututxline(&utmp);
++
++ endutxent();
++
++ job_process_handler (NULL, 1, NIH_CHILD_EXITED, 0);
++
++ setutxent();
++
++ utmptr = getutxent();
++ TEST_NE_P(utmptr, NULL);
++ TEST_EQ(utmptr->ut_pid, 2);
++ TEST_EQ(utmptr->ut_type, USER_PROCESS);
++
++ utmptr = getutxent();
++ TEST_NE_P(utmptr, NULL);
++ TEST_EQ(utmptr->ut_pid, 1);
++ TEST_EQ(utmptr->ut_type, DEAD_PROCESS);
++
++ nih_free (job);
++ }
++}
++
++
+ int
+ main (int argc,
+ char *argv[])
+@@ -4505,6 +4672,7 @@ main (int argc,
+ test_spawn ();
+ test_kill ();
+ test_handler ();
++ test_utmp ();
+
+ test_find ();
+
More information about the scm-commits
mailing list