diff options
author | Dan Nicolaescu <[email protected]> | 2008-10-26 19:05:47 +0000 |
---|---|---|
committer | Dan Nicolaescu <[email protected]> | 2008-10-26 19:05:47 +0000 |
commit | 5790ef40bae85dc23ae404098198879106057697 (patch) | |
tree | b479642da69b4f0531ed8efefc739e31cbcaa8e1 /src | |
parent | 91c491e0518186d86e66413736025f2f585daf60 (diff) |
* startup.el (command-line): Call daemon-initialized after
starting the server.
* emacs.c (daemon_pipe): New variable
(main): Create a pipe before forking, make the parent exit only after
the child has closed its end of the pipe. Move closing the
descriptors ...
(Fdaemon_initialized): ... here. New function.
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 8 | ||||
-rw-r--r-- | src/emacs.c | 83 |
2 files changed, 83 insertions, 8 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 3dd47c8484..f86b94ed7d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2008-10-26 Romain Francoise <[email protected]> + + * emacs.c (daemon_pipe): New variable + (main): Create a pipe before forking, make the parent exit only after + the child has closed its end of the pipe. Move closing the + descriptors ... + (Fdaemon_initialized): ... here. New function. + 2008-10-26 Stefan Monnier <[email protected]> * chartab.c (Foptimize_char_table): Make sure `ascii' doesn't point to diff --git a/src/emacs.c b/src/emacs.c index 4712e9c1d0..bcc7fb0579 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -238,6 +238,10 @@ int noninteractive1; /* Nonzero means Emacs was started as a daemon. */ int is_daemon = 0; +/* Pipe used to send exit notification to the daemon parent at + startup. */ +static int daemon_pipe[2]; + /* Save argv and argc. */ char **initial_argv; int initial_argc; @@ -1073,21 +1077,54 @@ main (int argc, char **argv) if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args)) { #ifndef DOS_NT - pid_t f = fork (); - int nfd; + pid_t f; + + /* 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); } - nfd = open ("/dev/null", O_RDWR); - dup2 (nfd, 0); - dup2 (nfd, 1); - dup2 (nfd, 2); - close (nfd); + /* Close unused reading end of the pipe. */ + close (daemon_pipe[0]); is_daemon = 1; #ifdef HAVE_SETSID setsid(); @@ -2388,6 +2425,35 @@ 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. */) + () +{ + int nfd; + + if (!is_daemon) + error ("This function can only be called if emacs is run as a daemon"); + + if (daemon_pipe[1] < 0) + error ("The daemon has already been initialized"); + + if (NILP (Vafter_init_time)) + error ("This function can only be called after loading the init files"); + + /* Get rid of stdin, stdout and stderr. */ + open ("/dev/null", O_RDWR); + dup2 (nfd, 0); + dup2 (nfd, 1); + dup2 (nfd, 2); + close (nfd); + + /* Closing the pipe will notify the parent that it can exit. */ + close (daemon_pipe[1]); + /* Set it to an invalid value so we know we've already run this function. */ + daemon_pipe[1] = -1; + return Qt; +} + void syms_of_emacs () { @@ -2407,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. |