summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/emacs/cmdargs.texi15
-rw-r--r--doc/emacs/glossary.texi4
-rw-r--r--doc/emacs/misc.texi9
-rw-r--r--doc/lispref/display.texi2
-rw-r--r--doc/lispref/os.texi17
-rw-r--r--etc/NEWS6
-rw-r--r--etc/emacs.service4
-rw-r--r--src/emacs.c296
-rw-r--r--src/lisp.h9
9 files changed, 202 insertions, 160 deletions
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;
-
- /* 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
-
- 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);
- }
+ 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.
+
+ 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 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 ();
-#else /* DAEMON_MUST_EXEC */
- 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];
-
- /* 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);
-
- 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 (daemon_type == 2)
+ {
+ pid_t f;
+#ifndef DAEMON_MUST_EXEC
- emacs_close (daemon_pipe[0]);
- exit (0);
- }
- if (f < 0)
- {
- emacs_perror ("fork");
- exit (EXIT_CANCELED);
- }
+ f = fork ();
+#else /* DAEMON_MUST_EXEC */
+ 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];
+
+ /* 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);
+
+ 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);
+ }
#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 : "");
-
- if (! (0 <= fdStrlen && fdStrlen < sizeof fdStr))
- {
- fprintf (stderr, "daemon: child name too long\n");
- exit (EXIT_CANNOT_INVOKE);
+ {
+ /* 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);
+ }
+
+ 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;
-
- /* 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;
+
+ 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;
+ }
+
/* 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)