Hello,
Attached patch tries to fix #183729.
If we assume that *getty takes care about setting INIT_PROCESS/LOGIN_PROCESS
itself, we need
just set DEAD_PROCESS for dead processes with pid in utmp table and log it into
wtmp.
Init goes through the utmp table, tries to find entry with dead process pid and
sets it
to DEAD_PROCESS. There is no need to create/set up "utmp" stanza.
Test covers utmp table with 2 entries and with 2 situation - process is in
LOGIN_PROCESS or USER_PROCESS.
Regards,
Petr
--
Petr Lautrbach, Red Hat, Inc.
=== modified file 'init/job_process.c'
--- old/init/job_process.c 2010-02-26 15:31:13 +0000
+++ new/init/job_process.c 2010-04-22 10:41:55 +0000
@@ -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>
@@ -965,6 +967,8 @@
int status)
{
int failed = FALSE, stop = FALSE, state = TRUE;
+ struct utmpx *utmptr;
+ struct timeval tv;
nih_assert (job != NULL);
@@ -1127,6 +1131,33 @@
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;
+ /* Update existing utmp file. */
+ setutxent();
+ 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;
=== modified file 'init/tests/test_job_process.c'
--- old/init/tests/test_job_process.c 2010-02-26 15:31:13 +0000
+++ new/init/tests/test_job_process.c 2010-04-22 10:42:00 +0000
@@ -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>
@@ -4468,6 +4470,171 @@
}
+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[])
@@ -4499,6 +4666,7 @@
test_spawn ();
test_kill ();
test_handler ();
+ test_utmp ();
test_find ();
--
upstart-devel mailing list
[email protected]
Modify settings or unsubscribe at:
https://lists.ubuntu.com/mailman/listinfo/upstart-devel