Commit 36b99556 authored by Glenn Morris's avatar Glenn Morris

Add --new-daemon, which 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.  (Bug#2677)
* src/emacs.c (daemon_type): New integer.
(usage, standard_args): Add --old-daemon and --new-daemon.
(main): Handle --old-daemon and --new-daemon arguments.
Restrict all the forking and complicated daemon stuff to old-daemon.
(Fdaemon_initialized): Handle new-style daemon.
* src/lisp.h (IS_DAEMON, DAEMON_RUNNING) [!WINDOWNT]:
Replace daemon_pipe with daemon_type.
* doc/emacs/cmdargs.texi (Initial Options):
* doc/emacs/glossary.texi (Glossary):
* doc/emacs/misc.texi (Emacs Server):
* doc/lispref/display.texi (Window Systems):
* doc/lispref/os.texi (Startup Summary): Related doc updates.
* etc/NEWS: Mention this.
* etc/emacs.service: Use Type=simple and --new-daemon.
parent 35007ad9
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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}.)
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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;
......
......@@ -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)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment