GNU bug report logs -
#1058
23.0.60; emacs --daemon should not return until socket is ready
Previous Next
Full log
Message #65 received at 1058 <at> emacsbugs.donarmstrong.com (full text, mbox):
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.