GNU bug report logs - #1058
23.0.60; emacs --daemon should not return until socket is ready

Previous Next

Package: emacs;

Reported by: SRS0+wOMF+22+gmail.com=trentbuck <at> internode.on.net

Date: Tue, 30 Sep 2008 14:10:04 UTC

Severity: normal

Done: Chong Yidong <cyd <at> stupidchicken.com>

Bug is archived. No further changes may be made.

Full log


Message #65 received at 1058 <at> emacsbugs.donarmstrong.com (full text, mbox):

From: Romain Francoise <romain <at> orebokech.com>
To: Dan Nicolaescu <dann <at> ics.uci.edu>
Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>, 1058 <at> debbugs.gnu.org,
        trentbuck <at> gmail.com
Subject: Re: bug#1058: 23.0.60; emacs --daemon should not return until socket is ready
Date: Thu, 02 Oct 2008 19:54:51 +0200
Here's version one of a patch for this, please let me know what you
think.

diff --git a/lisp/startup.el b/lisp/startup.el
index 5bd73f9..22c92c5 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -1224,7 +1224,8 @@ opening the first frame (e.g. open a connection to an X server).")
   ;; processing all command line arguments to allow e.g. `server-name'
   ;; to be changed before the server starts.
   (when (daemonp)
-    (server-start))
+    (server-start)
+    (daemon-initialized))
 
   ;; Run emacs-session-restore (session management) if started by
   ;; the session manager and we have a session manager connection.
diff --git a/src/emacs.c b/src/emacs.c
index f94d2d3..d4d16b7 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -235,6 +235,13 @@ int noninteractive1;
 /* Nonzero means Emacs was started as a daemon.  */
 int is_daemon = 0;
 
+/* Set nonzero after the daemon has finished initializing.  */
+int daemon_initialized = 0;
+
+/* Pipe used to send exit notification to the daemon parent at
+   startup.  */
+int daemon_pipe[2];
+
 /* Save argv and argc.  */
 char **initial_argv;
 int initial_argc;
@@ -1074,16 +1081,56 @@ main (int argc, char **argv)
   if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args))
     {
 #ifndef DOS_NT
-      pid_t f = fork ();
+      pid_t f;
       int nfd;
+
+      /* Start as a daemon: fork a new child process which will run the
+	 rest of the initialization code, then exit.
+
+	 We want to avoid exiting before the server socket is ready, so
+	 use a pipe for synchronization.  The parent waits for the child
+	 to close its end of the pipe (using `daemon-initialized')
+	 before exiting.  */
+      if (pipe (daemon_pipe) == -1)
+	{
+	  fprintf (stderr, "Cannot pipe!\n");
+	  exit (1);
+	}
+
+      f = fork ();
       if (f > 0)
-	exit (0);
+	{
+	  int retval;
+	  char buf[1];
+
+	  /* Close unused writing end of the pipe.  */
+	  close (daemon_pipe[1]);
+
+	  /* Just wait for the child to close its end of the pipe.  */
+	  do
+	    {
+	      retval = read (daemon_pipe[0], &buf, 1);
+	    }
+	  while (retval == -1 && errno == EINTR);
+
+	  if (retval < 0)
+	    {
+	      fprintf (stderr, "Error reading status from child\n");
+	      exit (1);
+	    }
+
+	  close (daemon_pipe[0]);
+	  exit (0);
+	}
       if (f < 0)
 	{
 	  fprintf (stderr, "Cannot fork!\n");
 	  exit (1);
 	}
 
+      /* Close unused reading end of the pipe.  */
+      close (daemon_pipe[0]);
+
       nfd = open ("/dev/null", O_RDWR);
       dup2 (nfd, 0);
       dup2 (nfd, 1);
@@ -2389,6 +2436,24 @@ DEFUN ("daemonp", Fdaemonp, Sdaemonp, 0, 0, 0,
   return is_daemon ? Qt : Qnil;
 }
 
+DEFUN ("daemon-initialized", Fdaemon_initialized, Sdaemon_initialized, 0, 0, 0,
+       doc: /* Mark the Emacs daemon as being initialized.  */)
+  ()
+{
+  if (is_daemon)
+    {
+      if (! daemon_initialized)
+	{
+	  /* Closing the pipe will notify the parent that it can exit. */
+	  close (daemon_pipe[1]);
+	  daemon_initialized = 1;
+	}
+    }
+  else
+    error ("Emacs was not started as a daemon");
+  return daemon_initialized ? Qt : Qnil;
+}
+
 void
 syms_of_emacs ()
 {
@@ -2408,6 +2473,7 @@ syms_of_emacs ()
   defsubr (&Sinvocation_name);
   defsubr (&Sinvocation_directory);
   defsubr (&Sdaemonp);
+  defsubr (&Sdaemon_initialized);
 
   DEFVAR_LISP ("command-line-args", &Vcommand_line_args,
 	       doc: /* Args passed by shell to Emacs, as a list of strings.




This bug report was last modified 16 years and 202 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.