diff -u upstart-0.6.5/debian/control upstart-0.6.5/debian/control --- upstart-0.6.5/debian/control +++ upstart-0.6.5/debian/control @@ -12,6 +12,7 @@ Replaces: upstart-job, sysvinit, upstart-compat-sysv, startup-tasks, system-services Conflicts: upstart-job, sysvinit, upstart-compat-sysv, startup-tasks, system-services Provides: upstart-job, upstart-compat-sysv, startup-tasks, system-services +Breaks: libc6 ( << 2.11.1-0ubuntu7.8 ) Description: event-based init daemon upstart is a replacement for the /sbin/init daemon which handles starting of tasks and services during boot, stopping them during diff -u upstart-0.6.5/debian/changelog upstart-0.6.5/debian/changelog --- upstart-0.6.5/debian/changelog +++ upstart-0.6.5/debian/changelog @@ -1,3 +1,12 @@ +upstart (0.6.5-8) lucid-proposed; urgency=low + + * Re-add upstream r977 to allow proper re-exec on shutdown (LP: #672177) + * debian/control: adding Breaks on eglibc version that disables + telinit u to avoid accidentally installing a version of libc6 that + will cause upstart to re-exec and lose its state. + + -- Clint Byrum Fri, 21 Jan 2011 08:21:18 -0800 + upstart (0.6.5-7) lucid-proposed; urgency=low * Apply patch from trunk to use /dev/null when /dev/console is unavailable diff -u upstart-0.6.5/init/main.c upstart-0.6.5/init/main.c --- upstart-0.6.5/init/main.c +++ upstart-0.6.5/init/main.c @@ -63,6 +63,9 @@ /* Prototypes for static functions */ #ifndef DEBUG static void crash_handler (int signum); +#endif /* DEBUG */ +static void term_handler (void *data, NihSignal *signal); +#ifndef DEBUG static void cad_handler (void *data, NihSignal *signal); static void kbd_handler (void *data, NihSignal *signal); static void pwr_handler (void *data, NihSignal *signal); @@ -259,8 +262,14 @@ /* SIGUSR1 instructs us to reconnect to D-Bus */ nih_signal_set_handler (SIGUSR1, nih_signal_handler); NIH_MUST (nih_signal_add_handler (NULL, SIGUSR1, usr1_handler, NULL)); -#endif /* DEBUG */ + /* SIGTERM instructs us to re-exec ourselves; this should be the + * last in the list to ensure that all other signals are handled + * before a SIGTERM. + */ + nih_signal_set_handler (SIGTERM, nih_signal_handler); + NIH_MUST (nih_signal_add_handler (NULL, SIGTERM, term_handler, NULL)); +#endif /* DEBUG */ /* Watch children for events */ NIH_MUST (nih_child_add_watch (NULL, -1, NIH_CHILD_ALL, @@ -474,7 +483,60 @@ /* Goodbye, cruel world. */ exit (signum); } +#endif + +/** + * term_handler: + * @data: unused, + * @signal: signal caught. + * + * This is called when we receive the TERM signal, which instructs us + * to reexec ourselves. + **/ +static void +term_handler (void *data, + NihSignal *signal) +{ + NihError *err; + const char *loglevel; + sigset_t mask, oldmask; + + nih_assert (argv0 != NULL); + nih_assert (signal != NULL); + + nih_warn (_("Re-executing %s"), argv0); + + /* Block signals while we work. We're the last signal handler + * installed so this should mean that they're all handled now. + * + * The child must make sure that it unblocks these again when + * it's ready. + */ + sigfillset (&mask); + sigprocmask (SIG_BLOCK, &mask, &oldmask); + /* Argument list */ + if (nih_log_priority <= NIH_LOG_DEBUG) { + loglevel = "--debug"; + } else if (nih_log_priority <= NIH_LOG_INFO) { + loglevel = "--verbose"; + } else if (nih_log_priority >= NIH_LOG_ERROR) { + loglevel = "--error"; + } else { + loglevel = NULL; + } + execl (argv0, argv0, "--restart", loglevel, NULL); + nih_error_raise_system (); + + err = nih_error_get (); + nih_error (_("Failed to re-execute %s: %s"), argv0, err->message); + nih_free (err); + + sigprocmask (SIG_SETMASK, &oldmask, NULL); +} + + +#ifndef DEBUG /** * cad_handler: * @data: unused,