[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