Merge authors:
  James Hunt (jamesodhunt)
Related merge proposals:
  https://code.launchpad.net/~jamesodhunt/upstart/bug-901038/+merge/231705
  proposed by: James Hunt (jamesodhunt)
  review: Approve - Steve Langasek (vorlon)
------------------------------------------------------------
revno: 1664 [merge]
committer: Steve Langasek <steve.langa...@canonical.com>
branch nick: upstream
timestamp: Mon 2014-09-08 08:18:43 -0700
message:
  Merge lp:~jamesodhunt/upstart/bug-901038
modified:
  ChangeLog
  util/telinit.c


--
lp:upstart
https://code.launchpad.net/~upstart-devel/upstart/trunk

Your team Upstart Reviewers is subscribed to branch lp:upstart.
To unsubscribe from this branch go to 
https://code.launchpad.net/~upstart-devel/upstart/trunk/+edit-subscription
=== modified file 'ChangeLog'
--- ChangeLog	2014-09-04 11:07:22 +0000
+++ ChangeLog	2014-09-08 15:18:43 +0000
@@ -1,3 +1,15 @@
+2014-09-08  James Hunt  <james.h...@ubuntu.com>
+
+	* util/telinit.c: Remove UPSTART_TELINIT_U_NO_WAIT check as it
+	  shouldn't realistically be needed.
+
+2014-08-21  James Hunt  <james.h...@ubuntu.com>
+
+	* util/telinit.c: restart_upstart():
+	  - Revert to synchronous behaviour coupled with unavoidable
+	    poll to ensure telinit only returns once a re-exec has
+	    completed (LP: #901038).
+
 2014-09-04  James Hunt  <james.h...@ubuntu.com>
 
 	* NEWS: Release 1.13.2

=== modified file 'util/telinit.c'
--- util/telinit.c	2014-03-10 13:43:50 +0000
+++ util/telinit.c	2014-09-08 10:12:10 +0000
@@ -160,27 +160,73 @@
 int
 restart_upstart (void)
 {
-	nih_local NihDBusProxy *upstart = NULL;
-	DBusPendingCall        *ret;
+	nih_local NihDBusProxy  *upstart = NULL;
+	NihError                *err;
+	int                      ret;
 
 	upstart = upstart_open (NULL);
 	if (! upstart)
 		return -1;
 
-	/* Fire and forget:
-	 *
-	 * Ask Upstart to restart itself using the async interface to
-	 * avoid the client-side complaining if and when it detects that
-	 * Upstart has severed all connections to perform the re-exec.
-	 */
-	ret = upstart_restart (upstart, NULL, NULL, NULL, 0);
-	dbus_connection_flush(upstart->connection);
-
-	/* We don't care about the return code, but we have to keep
-	 * the compiler happy.
-	 */
-	if (ret != (DBusPendingCall *)TRUE)
-		return 0;
+	/* Ask Upstart to restart itself.
+	 *
+	 * Since it is not possible to serialise a D-Bus connection,
+	 * Upstart is forced to sever all D-Bus client connections,
+	 * including this one.
+	 *
+	 * Further, since the user expects telinit to block _until the
+	 * re-exec has finished and Upstart is accepting connections
+	 * once again_, the only solution is to wait for the forced
+	 * disconnect, then poll until it is possible to create a new
+	 * connection.
+	 *
+	 * Note that we don't (can't) care about the return code since
+	 * it's not reliable:
+	 *
+	 * - either the re-exec request completed and D-Bus returned zero
+	 *   before Upstart started the re-exec.
+	 *
+	 * - or the re-exec request completed but upstart started the
+	 *   re-exec (severing all D-Bus connections) before D-Bus got a
+	 *   chance to finish cleanly meaning we receive a return of -1.
+	 *
+	 * We cannot know exactly what happened so have to allow for
+	 * both scenarios. Note the implicit assumption that the re-exec
+	 * request itself was accepted. If this assumption is incorrect
+	 * (should not be possible), the worst case scenario is that
+	 * upstart does not re-exec and then we quickly drop out of the
+	 * reconnect block since it never went offline.
+	 */
+	ret = upstart_restart_sync (NULL, upstart);
+
+	if (ret < 0) {
+		err = nih_error_get ();
+		nih_free (err);
+	}
+
+	nih_free (upstart);
+
+	nih_debug ("Waiting for upstart to finish re-exec");
+
+	/* We believe Upstart is now in the process of
+	 * re-exec'ing so attempt forever to reconnect.
+	 *
+	 * This sounds dangerous but there is no other option,
+	 * and a connection must be possible unless the system
+	 * is completely broken.
+	 */
+	while (TRUE) {
+
+		upstart = upstart_open (NULL);
+		if (upstart)
+			break;
+
+		err = nih_error_get ();
+		nih_free (err);
+
+		/* Avoid DoS'ing the system whilst we wait */
+		usleep (100000);
+	}
 
 	return 0;
 }

-- 
upstart-devel mailing list
upstart-devel@lists.ubuntu.com
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/upstart-devel

Reply via email to