[maemo-commits] [maemo-commits] r15055 - in projects/haf/trunk/maemo-launcher: . launcher

From: subversion at stage.maemo.org subversion at stage.maemo.org
Date: Thu Jan 10 23:38:22 EET 2008
Author: guillem
Date: 2008-01-10 23:38:22 +0200 (Thu, 10 Jan 2008)
New Revision: 15055

Modified:
   projects/haf/trunk/maemo-launcher/ChangeLog
   projects/haf/trunk/maemo-launcher/launcher/Makefile.am
   projects/haf/trunk/maemo-launcher/launcher/launcher.c
Log:
Support hot-swapping the in-memory maemo-launcher

Add state persistence support and reexectuion of itself on SIGUSR1, to
support clean package upgrades.


Modified: projects/haf/trunk/maemo-launcher/ChangeLog
===================================================================
--- projects/haf/trunk/maemo-launcher/ChangeLog	2008-01-10 21:21:51 UTC (rev 15054)
+++ projects/haf/trunk/maemo-launcher/ChangeLog	2008-01-10 21:38:22 UTC (rev 15055)
@@ -1,5 +1,26 @@
 2008-01-10  Guillem Jover  <guillem.jover at nokia.com>
 
+	* launcher/Makefile.am (maemo_launcher_SOURCES): Add 'comm_msg.c' and
+	'comm_msg.h'.
+	* launcher/launcher.c: Include "comm_msg.h".
+	(LAUNCHER_STATEFILE): New macro.
+	(statefilename): New variable.
+	(sigreexec_catched): Likewise.
+	(clean_daemon): Unlink statefilename.
+	(LAUNCHER_STATE_SIG): New macro.
+	(store_state): New function.
+	(load_state): Likewise.
+	(sigreexec_handler): Likewise.
+	(sigs_init): Initialize SIGUSR1 to sigreexec_handler.
+	(sigs_restore): Restore SIGUSR1.
+	(sigs_interrupt): Allow SIGUSR1 to interrupt syscalls.
+	(main): Try to load the state file, and fallback to normal
+	initialization if that fails. Only daemonize and create a pid file
+	if not loading the state file. Handle sigreexec_catched in the main
+	event loop to store the cache, and reexec self.
+
+2008-01-10  Guillem Jover  <guillem.jover at nokia.com>
+
 	* launcher/comm_msg.h: New file.
 	* launcher/comm_msg.c: Likewise.
 	* launcher/test_lib.h: Likewise.

Modified: projects/haf/trunk/maemo-launcher/launcher/Makefile.am
===================================================================
--- projects/haf/trunk/maemo-launcher/launcher/Makefile.am	2008-01-10 21:21:51 UTC (rev 15054)
+++ projects/haf/trunk/maemo-launcher/launcher/Makefile.am	2008-01-10 21:38:22 UTC (rev 15055)
@@ -41,7 +41,8 @@
 maemo_launcher_HEADERS = booster_api.h
 maemo_launcher_SOURCES = \
 	launcher.c report.c report.h booster.c booster.h \
-	invokelib.c invokelib.h comm_dbus.c comm_dbus.h \
+	invokelib.c invokelib.h \
+	comm_msg.c comm_msg.h comm_dbus.c comm_dbus.h \
 	prog.c prog.h
 maemo_launcher_CPPFLAGS = \
 	$(DBUS_CFLAGS) \

Modified: projects/haf/trunk/maemo-launcher/launcher/launcher.c
===================================================================
--- projects/haf/trunk/maemo-launcher/launcher/launcher.c	2008-01-10 21:21:51 UTC (rev 15054)
+++ projects/haf/trunk/maemo-launcher/launcher/launcher.c	2008-01-10 21:38:22 UTC (rev 15055)
@@ -1,7 +1,7 @@
 /*
  * $Id$
  *
- * Copyright (C) 2005, 2006, 2007 Nokia Corporation
+ * Copyright (C) 2005, 2006, 2007, 2008 Nokia Corporation
  *
  * Authors: Michael Natterer <mitch at imendio.com>
  *          Guillem Jover <guillem.jover at nokia.com>
@@ -43,12 +43,14 @@
 
 #include "report.h"
 #include "invokelib.h"
+#include "comm_msg.h"
 #include "comm_dbus.h"
 #include "booster.h"
 #include "prog.h"
 
 /* FIXME: Should go into '/var/run/'. */
 #define LAUNCHER_PIDFILE "/tmp/"PROG_NAME".pid"
+#define LAUNCHER_STATEFILE "/tmp/"PROG_NAME".state"
 
 typedef struct
 {
@@ -65,9 +67,11 @@
 } kindergarten_t;
 
 static char *pidfilename = LAUNCHER_PIDFILE;
+static char *statefilename = LAUNCHER_STATEFILE;
 static pid_t is_parent = 1;
 static volatile bool sigchild_catched = false;
 static volatile bool sighup_catched = false;
+static volatile bool sigreexec_catched = false;
 static bool send_app_died = false;
 
 #define OOM_ENABLE "0"
@@ -358,6 +362,7 @@
 {
   if (is_parent)
   {
+    unlink(statefilename);
     unlink(pidfilename);
     unlink(INVOKER_SOCK);
     killpg(0, signal);
@@ -537,6 +542,96 @@
   }
 }
 
+/* Persistence support */
+
+#define LAUNCHER_STATE_SIG "MLSF0.0"
+
+static bool
+store_state(kindergarten_t *childs, int invoker_fd)
+{
+  int i;
+  int fd;
+  child_t *list = childs->list;
+  comm_msg_t *msg;
+
+  unlink(statefilename);
+
+  fd = open(statefilename, O_WRONLY | O_CREAT, 0644);
+  if (fd < 0)
+  {
+    error("opening persistence file '%s'\n", statefilename);
+    return false;
+  }
+
+  msg = comm_msg_new(512);
+
+  comm_msg_pack_str(msg, LAUNCHER_STATE_SIG);
+  comm_msg_pack_int(msg, invoker_fd);
+  comm_msg_pack_int(msg, childs->used);
+
+  for (i = 0; i < childs->used; i++)
+  {
+    comm_msg_pack_int(msg, list[i].pid);
+    comm_msg_pack_int(msg, list[i].sock);
+    comm_msg_pack_str(msg, list[i].name);
+  }
+
+  comm_msg_send(fd, msg);
+
+  close(fd);
+
+  return true;
+}
+
+static kindergarten_t *
+load_state(int *invoker_fd)
+{
+  int i;
+  int fd;
+  uint32_t w;
+  const char *s;
+  kindergarten_t *childs;
+  child_t *list;
+  comm_msg_t *msg;
+
+  fd = open(statefilename, O_RDONLY);
+  if (fd < 0)
+  {
+    if (errno != ENOENT)
+      error("opening persistence file '%s'\n", statefilename);
+    return NULL;
+  }
+
+  msg = comm_msg_new(512);
+  comm_msg_recv(fd, msg);
+
+  close(fd);
+
+  comm_msg_unpack_str(msg, &s);
+  if (strcmp(LAUNCHER_STATE_SIG, s) != 0)
+  {
+    error("wrong signature on persistence file '%s'\n", statefilename);
+    return NULL;
+  }
+
+  comm_msg_unpack_int(msg, invoker_fd);
+
+  comm_msg_unpack_int(msg, &w);
+  childs = kindergarten_new(w);
+  childs->used = w;
+  list = childs->list;
+
+  for (i = 0; i < childs->used; i++)
+  {
+    comm_msg_unpack_int(msg, &list[i].pid);
+    comm_msg_unpack_int(msg, &list[i].sock);
+    comm_msg_unpack_str(msg, &s);
+    list[i].name = strdup(s);
+  }
+
+  return childs;
+}
+
 static void
 sigchild_handler(int sig)
 {
@@ -550,6 +645,12 @@
 }
 
 static void
+sigreexec_handler(int sig)
+{
+  sigreexec_catched = true;
+}
+
+static void
 sigs_init(void)
 {
   struct sigaction sig;
@@ -569,6 +670,9 @@
 
   sig.sa_handler = sighup_handler;
   sigaction(SIGHUP, &sig, NULL);
+
+  sig.sa_handler = sigreexec_handler;
+  sigaction(SIGUSR1, &sig, NULL);
 }
 
 static void
@@ -585,12 +689,14 @@
   sigaction(SIGTERM, &sig, NULL);
   sigaction(SIGCHLD, &sig, NULL);
   sigaction(SIGHUP, &sig, NULL);
+  sigaction(SIGUSR1, &sig, NULL);
 }
 
 static void
 sigs_interrupt(int flag)
 {
   siginterrupt(SIGCHLD, flag);
+  siginterrupt(SIGUSR1, flag);
 }
 
 static void
@@ -694,6 +800,7 @@
   int fd;
   bool daemon = false;
   bool quiet = false;
+  bool upgrading = false;
 
   /*
    * Parse arguments.
@@ -736,22 +843,32 @@
   env_init();
   fs_init();
 
-  /* Setup child tracking. */
-  kg = kindergarten_new(initial_child_slots);
+  kg = load_state(&fd);
 
-  /* Setup the conversation channel with the invoker. */
-  fd = invoked_init();
+  if (kg)
+    upgrading = true;
+  else
+  {
+    /* Setup child tracking. */
+    kg = kindergarten_new(initial_child_slots);
 
-  if (daemon)
-    daemonize();
+    /* Setup the conversation channel with the invoker. */
+    fd = invoked_init();
 
+    if (daemon)
+      daemonize();
+  }
+
   /* Protect us from the oom monster. */
   rise_oom_defense(getpid());
 
   if (quiet)
     console_quiet();
 
-  create_pidfile();
+  if (upgrading)
+    info("restored persitent state\n");
+  else
+    create_pidfile();
 
   /*
    * Application invokation loop.
@@ -781,6 +898,18 @@
       sighup_catched = false;
     }
 
+    if (sigreexec_catched)
+    {
+      info("storing kindergarten state\n");
+      store_state(kg, fd);
+
+      info("reexecuting self\n");
+      execv(argv[0], argv);
+
+      error("while trying to reexec self, trying to continue\n");
+      sigreexec_catched = false;
+    }
+
     /* Minimal error handling. */
     if (sd < 0)
     {


More information about the maemo-commits mailing list