]> git.eshelyaron.com Git - emacs.git/commitdiff
Add --new-daemon, which runs in the foreground and does not fork
authorGlenn Morris <rgm@gnu.org>
Wed, 16 Nov 2016 07:28:47 +0000 (23:28 -0800)
committerGlenn Morris <rgm@gnu.org>
Wed, 16 Nov 2016 07:28:47 +0000 (23:28 -0800)
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.

doc/emacs/cmdargs.texi
doc/emacs/glossary.texi
doc/emacs/misc.texi
doc/lispref/display.texi
doc/lispref/os.texi
etc/NEWS
etc/emacs.service
src/emacs.c
src/lisp.h

index 444d30527f8fc8ed1122225575bd0e66ac5278a5..8d3d936b7b38df2ca44e74d7d205088e04dff846 100644 (file)
@@ -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
index bce97dacee2b5a01999d331cbe13127c8801acfb..d6489390ea5a20742eacf645c782e2f5834ac1de 100644 (file)
@@ -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
index cb0a11605161c4e36b03bfd7901dae9e4c7ed678..2290dec31e290f9a5801daa74a9dfa8de0dc83d6 100644 (file)
@@ -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
index 381edbac48a7a25a7851d17f59b344d592fcf78b..d050738d80fc5e578c8797dd97a0c3b8f0d172a0 100644 (file)
@@ -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}.)
index 97b086c0d373f6c2f6615db80938803d85c6c949..3312705e167ac6f6f4973eb0fbc6070544bbbc60 100644 (file)
@@ -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
index 34d64bfac33dd305568425122c6d550d3befc3e7..15c264f582c89ab7ada08c46e8bd60412b6c17ce 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -64,6 +64,12 @@ affected by this, as SGI stopped supporting IRIX in December 2013.
 \f
 * 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'.
+
 \f
 * Changes in Emacs 26.1
 
index 92cdeb5cf49ecd6d29a01836388ec866ef1d711a..d9f7fc569d2f25eb0d6a8009cb3c1adeafeaf73d 100644 (file)
@@ -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
index aeba9631696a360bdc9b98e960dd4eba0433b384..92cbb0863392eb2699a7770fde4b20574bcae85a 100644 (file)
@@ -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;
index aaa442327201e9dee3eeb3395dbc74add15025c4..e087828d94f7ccda6281989288808e1c176d106f 100644 (file)
@@ -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)