diff --git a/doc/emacs/cmdargs.texi b/doc/emacs/cmdargs.texi index 444d30527f8..8d3d936b7b3 100644 --- a/doc/emacs/cmdargs.texi +++ b/doc/emacs/cmdargs.texi @@ -334,17 +334,18 @@ setting @code{inhibit-x-resources} to @code{t} (@pxref{Resources}). @item -daemon @opindex -daemon -@itemx --daemon +@itemx --daemon[=@var{name}] @opindex --daemon +@itemx --old-daemon[=@var{name}] +@itemx --new-daemon[=@var{name}] Start Emacs as a daemon---after Emacs starts up, it starts the Emacs -server and disconnects from the terminal without opening any frames. +server without opening any frames. +(Optionally, you can specify an explicit @var{name} for the server.) You can then use the @command{emacsclient} command to connect to Emacs for editing. @xref{Emacs Server}, for information about using Emacs -as a daemon. - -@item -daemon=@var{SERVER-NAME} -Start emacs in background as a daemon, and use @var{SERVER-NAME} as -the server name. +as a daemon. An ``old-style'' daemon disconnects from the terminal +and runs in the background (@samp{--daemon} is an alias for +@samp{--old-daemon}). @item --no-desktop @opindex --no-desktop diff --git a/doc/emacs/glossary.texi b/doc/emacs/glossary.texi index bce97dacee2..d6489390ea5 100644 --- a/doc/emacs/glossary.texi +++ b/doc/emacs/glossary.texi @@ -338,8 +338,8 @@ or by rebinding key sequences (@pxref{Keymaps}). @item Daemon A daemon is a standard term for a system-level process that runs in the background. Daemons are often started when the system first starts up. -When Emacs runs in daemon-mode, it runs in the background and does not -open a display. You can then connect to it with the +When Emacs runs in daemon-mode, it does not +open a display. You connect to it with the @command{emacsclient} program. @xref{Emacs Server}. @item Default Argument diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index cb0a1160516..2290dec31e2 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi @@ -1583,11 +1583,10 @@ dies with the Emacs process. @cindex daemon, Emacs @item -Run Emacs as a @dfn{daemon}, using the @samp{--daemon} command-line -option. @xref{Initial Options}. When Emacs is started this way, it -calls @code{server-start} after initialization, and returns control to -the calling terminal instead of opening an initial frame; it then -waits in the background, listening for edit requests. +Run Emacs as a @dfn{daemon}, using one of the @samp{--daemon} command-line +options. @xref{Initial Options}. When Emacs is started this way, it +calls @code{server-start} after initialization and does not open an +initial frame. It then waits for edit requests from clients. @cindex systemd unit file @item diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 381edbac48a..d050738d80f 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -7166,7 +7166,7 @@ Emacs is displaying the frame on a character-based terminal. @defvar initial-window-system This variable holds the value of @code{window-system} used for the first frame created by Emacs during startup. (When Emacs is invoked -with the @option{--daemon} option, it does not create any initial +as a daemon, it does not create any initial frames, so @code{initial-window-system} is @code{nil}, except on MS-Windows, where it is still @code{w32}. @xref{Initial Options, daemon,, emacs, The GNU Emacs Manual}.) diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index 97b086c0d37..3312705e167 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -112,8 +112,8 @@ compiled into the Emacs executable when it was built. It runs the normal hook @code{before-init-hook}. @item -If appropriate, it creates a graphical frame. This is not done if the -options @samp{--batch} or @samp{--daemon} were specified. +If appropriate, it creates a graphical frame. This is not done in +batch (noninteractive) or daemon mode. @item It initializes the initial frame's faces, and sets up the menu bar @@ -256,10 +256,10 @@ options were specified. @c last few bits of command-line-1 are not done in batch mode. @item -If the option @code{--daemon} was specified, it calls -@code{server-start}, and on Posix systems also detaches from the -controlling terminal. @xref{Emacs Server,,, emacs, The GNU Emacs -Manual}. +If a daemon was requested, it calls @code{server-start}. +(On Posix systems, if a background daemon was requested, it then +detaches from the controlling terminal.) @xref{Emacs +Server,,, emacs, The GNU Emacs Manual}. @item If started by the X session manager, it calls @@ -337,7 +337,10 @@ Do not display a splash screen. Run without an interactive terminal. @xref{Batch Mode}. @item --daemon -Do not initialize any display; just start a server in the background. +@itemx --old-daemon +@itemx --new-daemon +Do not initialize any display; just start a server. +(An ``old-style'' daemon automatically runs in the background.) @item --no-init-file @itemx -q diff --git a/etc/NEWS b/etc/NEWS index 34d64bfac33..15c264f582c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -64,6 +64,12 @@ affected by this, as SGI stopped supporting IRIX in December 2013. * Startup Changes in Emacs 26.1 +** New option '--new-daemon'. This is the same as '--daemon', except +it runs in the foreground and does not fork. This is intended for +modern init systems such as systemd, which manage many of the traditional +aspects of daemon behavior themselves. '--old-daemon' is now an alias +for '--daemon'. + * Changes in Emacs 26.1 diff --git a/etc/emacs.service b/etc/emacs.service index 92cdeb5cf49..d9f7fc569d2 100644 --- a/etc/emacs.service +++ b/etc/emacs.service @@ -7,8 +7,8 @@ Description=Emacs text editor Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/ [Service] -Type=forking -ExecStart=emacs --daemon +Type=simple +ExecStart=emacs --new-daemon ExecStop=emacsclient --eval "(kill-emacs)" Environment=SSH_AUTH_SOCK=%t/keyring/ssh Restart=on-failure diff --git a/src/emacs.c b/src/emacs.c index aeba9631696..92cbb086339 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -162,8 +162,8 @@ char *stack_bottom; static uprintmax_t heap_bss_diff; #endif -/* To run as a daemon under Cocoa or Windows, we must do a fork+exec, - not a simple fork. +/* To run as a background daemon under Cocoa or Windows, + we must do a fork+exec, not a simple fork. On Cocoa, CoreFoundation lib fails in forked process: http://developer.apple.com/ReleaseNotes/ @@ -190,9 +190,12 @@ bool build_details; /* Name for the server started by the daemon.*/ static char *daemon_name; +/* 0 not a daemon, 1 new-style (foreground), 2 old-style (background). */ +int daemon_type; + #ifndef WINDOWSNT -/* Pipe used to send exit notification to the daemon parent at - startup. */ +/* Pipe used to send exit notification to the background daemon parent at + startup. On Windows, we use a kernel event instead. */ int daemon_pipe[2]; #else HANDLE w32_daemon_event; @@ -223,7 +226,8 @@ Initialization options:\n\ "\ --batch do not do interactive display; implies -q\n\ --chdir DIR change to directory DIR\n\ ---daemon[=NAME] start a (named) server in the background\n\ +--daemon, --old-daemon[=NAME] start a (named) server in the background\n\ +--new-daemon[=NAME] start a (named) server in the foreground\n\ --debug-init enable Emacs Lisp debugger for init file\n\ --display, -d DISPLAY use X server DISPLAY\n\ ", @@ -977,6 +981,8 @@ main (int argc, char **argv) exit (0); } + daemon_type = 0; + #ifndef WINDOWSNT /* Make sure IS_DAEMON starts up as false. */ daemon_pipe[1] = 0; @@ -987,38 +993,52 @@ main (int argc, char **argv) int sockfd = -1; - if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args) - || argmatch (argv, argc, "-daemon", "--daemon", 5, &dname_arg, &skip_args)) + if (argmatch (argv, argc, "-new-daemon", "--new-daemon", 10, NULL, &skip_args) + || argmatch (argv, argc, "-new-daemon", "--new-daemon", 10, &dname_arg, &skip_args)) + { + daemon_type = 1; /* foreground */ + } + else if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args) + || argmatch (argv, argc, "-daemon", "--daemon", 5, &dname_arg, &skip_args) + || argmatch (argv, argc, "-old-daemon", "--old-daemon", 10, NULL, &skip_args) + || argmatch (argv, argc, "-old-daemon", "--old-daemon", 10, &dname_arg, &skip_args)) + { + daemon_type = 2; /* background */ + } + + + if (daemon_type > 0) { #ifndef DOS_NT - pid_t f; + if (daemon_type == 2) + { + /* Start as a background daemon: fork a new child process which + will run the rest of the initialization code, then exit. - /* Start as a daemon: fork a new child process which will run the - rest of the initialization code, then exit. + Detaching a daemon requires the following steps: + - fork + - setsid + - exit the parent + - close the tty file-descriptors - Detaching a daemon requires the following steps: - - fork - - setsid - - exit the parent - - close the tty file-descriptors + We only want to do the last 2 steps once the daemon is ready to + serve requests, i.e. after loading .emacs (initialization). + OTOH initialization may start subprocesses (e.g. ispell) and these + should be run from the proper process (the one that will end up + running as daemon) and with the proper "session id" in order for + them to keep working after detaching, so fork and setsid need to be + performed before initialization. - We only want to do the last 2 steps once the daemon is ready to - serve requests, i.e. after loading .emacs (initialization). - OTOH initialization may start subprocesses (e.g. ispell) and these - should be run from the proper process (the one that will end up - running as daemon) and with the proper "session id" in order for - them to keep working after detaching, so fork and setsid need to be - performed before initialization. - - 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 (emacs_pipe (daemon_pipe) != 0) - { - fprintf (stderr, "Cannot pipe!\n"); - exit (1); - } + 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 (emacs_pipe (daemon_pipe) != 0) + { + fprintf (stderr, "Cannot pipe!\n"); + exit (1); + } + } /* daemon_type == 2 */ #ifdef HAVE_LIBSYSTEMD /* Read the number of sockets passed through by systemd. */ @@ -1035,99 +1055,105 @@ main (int argc, char **argv) sockfd = SD_LISTEN_FDS_START; #endif /* HAVE_LIBSYSTEMD */ -#ifndef DAEMON_MUST_EXEC #ifdef USE_GTK fprintf (stderr, "\nWarning: due to a long standing Gtk+ bug\nhttp://bugzilla.gnome.org/show_bug.cgi?id=85715\n\ Emacs might crash when run in daemon mode and the X11 connection is unexpectedly lost.\n\ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem.\n"); #endif /* USE_GTK */ - f = fork (); + + if (daemon_type == 2) + { + pid_t f; +#ifndef DAEMON_MUST_EXEC + + f = fork (); #else /* DAEMON_MUST_EXEC */ - if (!dname_arg || !strchr (dname_arg, '\n')) - f = fork (); /* in orig */ - else - f = 0; /* in exec'd */ + if (!dname_arg || !strchr (dname_arg, '\n')) + f = fork (); /* in orig */ + else + f = 0; /* in exec'd */ #endif /* !DAEMON_MUST_EXEC */ - if (f > 0) - { - int retval; - char buf[1]; + if (f > 0) + { + int retval; + char buf[1]; - /* Close unused writing end of the pipe. */ - emacs_close (daemon_pipe[1]); + /* Close unused writing end of the pipe. */ + emacs_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); + /* 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); - } - else if (retval == 0) - { - fprintf (stderr, "Error: server did not start correctly\n"); - exit (1); - } + if (retval < 0) + { + fprintf (stderr, "Error reading status from child\n"); + exit (1); + } + else if (retval == 0) + { + fprintf (stderr, "Error: server did not start correctly\n"); + exit (1); + } - emacs_close (daemon_pipe[0]); - exit (0); - } - if (f < 0) - { - emacs_perror ("fork"); - exit (EXIT_CANCELED); - } + emacs_close (daemon_pipe[0]); + exit (0); + } + if (f < 0) + { + emacs_perror ("fork"); + exit (EXIT_CANCELED); + } #ifdef DAEMON_MUST_EXEC - { - /* In orig process, forked as child, OR in exec'd. */ - if (!dname_arg || !strchr (dname_arg, '\n')) - { /* In orig, child: now exec w/special daemon name. */ - char fdStr[80]; - int fdStrlen = - snprintf (fdStr, sizeof fdStr, - "--daemon=\n%d,%d\n%s", daemon_pipe[0], - daemon_pipe[1], dname_arg ? dname_arg : ""); + { + /* In orig process, forked as child, OR in exec'd. */ + if (!dname_arg || !strchr (dname_arg, '\n')) + { /* In orig, child: now exec w/special daemon name. */ + char fdStr[80]; + int fdStrlen = + snprintf (fdStr, sizeof fdStr, + "--old-daemon=\n%d,%d\n%s", daemon_pipe[0], + daemon_pipe[1], dname_arg ? dname_arg : ""); - if (! (0 <= fdStrlen && fdStrlen < sizeof fdStr)) - { - fprintf (stderr, "daemon: child name too long\n"); - exit (EXIT_CANNOT_INVOKE); + if (! (0 <= fdStrlen && fdStrlen < sizeof fdStr)) + { + fprintf (stderr, "daemon: child name too long\n"); + exit (EXIT_CANNOT_INVOKE); + } + + argv[skip_args] = fdStr; + + fcntl (daemon_pipe[0], F_SETFD, 0); + fcntl (daemon_pipe[1], F_SETFD, 0); + execvp (argv[0], argv); + emacs_perror (argv[0]); + exit (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE); } - argv[skip_args] = fdStr; - - fcntl (daemon_pipe[0], F_SETFD, 0); - fcntl (daemon_pipe[1], F_SETFD, 0); - execvp (argv[0], argv); - emacs_perror (argv[0]); - exit (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE); - } - - /* In exec'd: parse special dname into pipe and name info. */ - if (!dname_arg || !strchr (dname_arg, '\n') - || strlen (dname_arg) < 1 || strlen (dname_arg) > 70) + /* In exec'd: parse special dname into pipe and name info. */ + if (!dname_arg || !strchr (dname_arg, '\n') + || strlen (dname_arg) < 1 || strlen (dname_arg) > 70) { fprintf (stderr, "emacs daemon: daemon name absent or too long\n"); exit (EXIT_CANNOT_INVOKE); } - dname_arg2[0] = '\0'; - sscanf (dname_arg, "\n%d,%d\n%s", &(daemon_pipe[0]), &(daemon_pipe[1]), - dname_arg2); - dname_arg = *dname_arg2 ? dname_arg2 : NULL; - fcntl (daemon_pipe[1], F_SETFD, FD_CLOEXEC); - } + dname_arg2[0] = '\0'; + sscanf (dname_arg, "\n%d,%d\n%s", &(daemon_pipe[0]), &(daemon_pipe[1]), + dname_arg2); + dname_arg = *dname_arg2 ? dname_arg2 : NULL; + fcntl (daemon_pipe[1], F_SETFD, FD_CLOEXEC); + } #endif /* DAEMON_MUST_EXEC */ - /* Close unused reading end of the pipe. */ - emacs_close (daemon_pipe[0]); + /* Close unused reading end of the pipe. */ + emacs_close (daemon_pipe[0]); - setsid (); + setsid (); + } /* daemon_type == 2 */ #elif defined(WINDOWSNT) /* Indicate that we want daemon mode. */ w32_daemon_event = CreateEvent (NULL, TRUE, FALSE, W32_DAEMON_EVENT); @@ -1138,7 +1164,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem exit (1); } #else /* MSDOS */ - fprintf (stderr, "This platform does not support the -daemon flag.\n"); + fprintf (stderr, "This platform does not support daemon mode.\n"); exit (1); #endif /* MSDOS */ if (dname_arg) @@ -1684,6 +1710,8 @@ static const struct standard_args standard_args[] = { "-batch", "--batch", 100, 0 }, { "-script", "--script", 100, 1 }, { "-daemon", "--daemon", 99, 0 }, + { "-old-daemon", "--old-daemon", 99, 0 }, + { "-new-daemon", "--new-daemon", 99, 0 }, { "-help", "--help", 90, 0 }, { "-nl", "--no-loadup", 70, 0 }, { "-nsl", "--no-site-lisp", 65, 0 }, @@ -2407,27 +2435,33 @@ from the parent process and its tty file descriptors. */) if (NILP (Vafter_init_time)) error ("This function can only be called after loading the init files"); #ifndef WINDOWSNT - int nfd; - /* Get rid of stdin, stdout and stderr. */ - nfd = emacs_open ("/dev/null", O_RDWR, 0); - err |= nfd < 0; - err |= dup2 (nfd, STDIN_FILENO) < 0; - err |= dup2 (nfd, STDOUT_FILENO) < 0; - err |= dup2 (nfd, STDERR_FILENO) < 0; - err |= emacs_close (nfd) != 0; + if (daemon_type == 2) + { + int nfd; + + /* Get rid of stdin, stdout and stderr. */ + nfd = emacs_open ("/dev/null", O_RDWR, 0); + err |= nfd < 0; + err |= dup2 (nfd, STDIN_FILENO) < 0; + err |= dup2 (nfd, STDOUT_FILENO) < 0; + err |= dup2 (nfd, STDERR_FILENO) < 0; + err |= emacs_close (nfd) != 0; + + /* Closing the pipe will notify the parent that it can exit. + FIXME: In case some other process inherited the pipe, closing it here + won't notify the parent because it's still open elsewhere, so we + additionally send a byte, just to make sure the parent really exits. + Instead, we should probably close the pipe in start-process and + call-process to make sure the pipe is never inherited by + subprocesses. */ + err |= write (daemon_pipe[1], "\n", 1) < 0; + err |= emacs_close (daemon_pipe[1]) != 0; + } - /* Closing the pipe will notify the parent that it can exit. - FIXME: In case some other process inherited the pipe, closing it here - won't notify the parent because it's still open elsewhere, so we - additionally send a byte, just to make sure the parent really exits. - Instead, we should probably close the pipe in start-process and - call-process to make sure the pipe is never inherited by - subprocesses. */ - err |= write (daemon_pipe[1], "\n", 1) < 0; - err |= emacs_close (daemon_pipe[1]) != 0; /* Set it to an invalid value so we know we've already run this function. */ - daemon_pipe[1] = -1; + daemon_type = -1; + #else /* WINDOWSNT */ /* Signal the waiting emacsclient process. */ err |= SetEvent (w32_daemon_event) == 0; diff --git a/src/lisp.h b/src/lisp.h index aaa44232720..e087828d94f 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4139,12 +4139,11 @@ extern bool no_site_lisp; /* True means put details like time stamps into builds. */ extern bool build_details; -/* Pipe used to send exit notification to the daemon parent at - startup. On Windows, we use a kernel event instead. */ #ifndef WINDOWSNT -extern int daemon_pipe[2]; -#define IS_DAEMON (daemon_pipe[1] != 0) -#define DAEMON_RUNNING (daemon_pipe[1] >= 0) +/* 0 not a daemon, 1 new-style (foreground), 2 old-style (background). */ +extern int daemon_type; +#define IS_DAEMON (daemon_type != 0) +#define DAEMON_RUNNING (daemon_type >= 0) #else /* WINDOWSNT */ extern void *w32_daemon_event; #define IS_DAEMON (w32_daemon_event != NULL)