unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Re: master 2c79a8f 2/2: Use posix_spawn if possible.
@ 2022-01-25  6:48 Saulius Menkevicius
  2022-01-25  8:41 ` Eli Zaretskii
  2022-01-25 13:15 ` master 2c79a8f 2/2: Use posix_spawn if possible Stefan Monnier
  0 siblings, 2 replies; 91+ messages in thread
From: Saulius Menkevicius @ 2022-01-25  6:48 UTC (permalink / raw)
  To: emacs-devel; +Cc: p.stephani2, alan, mituharu

Hi,

I know this has been merged a couple of months ago to `master` but I 
would like to report breakage that occurs due to that commit.

We have csharp-ls (C#) and fsautocomplete (F#) LSP servers that stopped 
working with that commit (git-bisected to 
a60053f8368e058229721f1bf1567c2b1676b239).

I did not delve too much into the details or prepare a minimal test case 
but this appears to be an interplay between dotnet runtime (v6) and 
posix_spawn.

Not sure if that warrants a revert but just a heads-up.

-Saulius




^ permalink raw reply	[flat|nested] 91+ messages in thread
* Re: master 2c79a8f 2/2: Use posix_spawn if possible.
@ 2021-11-08 11:00 Aaron Jensen
  2021-11-08 11:03 ` Aaron Jensen
                   ` (2 more replies)
  0 siblings, 3 replies; 91+ messages in thread
From: Aaron Jensen @ 2021-11-08 11:00 UTC (permalink / raw)
  To: emacs-devel; +Cc: Eli Zaretskii, Alan Third, YAMAMOTO Mitsuharu

[-- Attachment #1: Type: text/plain, Size: 350 bytes --]

Hi all,

Attached is the posix spawn patch adapted to be only effective on
Darwin. I chose to leave the patch as-is aside from adding the
additional conditional, but let me know if I should do something
different. It wasn't clear where things stood in terms of whether or
not we would ever want to use posix_spawn on non-darwin OSes.

Thanks,

Aaron

[-- Attachment #2: 0001-Use-posix_spawn-if-possible-on-Darwin.patch --]
[-- Type: application/octet-stream, Size: 8764 bytes --]

From 8055b42c60b4178707074c2dfb4530aeb926c59d Mon Sep 17 00:00:00 2001
From: Aaron Jensen <aaronjensen@gmail.com>
Date: Mon, 8 Nov 2021 05:38:11 -0500
Subject: [PATCH] Use posix_spawn if possible on Darwin.

posix_spawn is less error-prone than vfork + execve, and can make
better use of system-specific enhancements like 'clone' on Linux.  Use
it if we don't need to configure a pseudoterminal.

* configure.ac (HAVE_SPAWN_H, HAVE_POSIX_SPAWN)
(HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR)
(HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NP)
(HAVE_POSIX_SPAWNATTR_SETFLAGS, HAVE_DECL_POSIX_SPAWN_SETSID): New
configuration variables.
* src/callproc.c (USABLE_POSIX_SPAWN): New configuration macro.
(emacs_posix_spawn_init_actions)
(emacs_posix_spawn_init_attributes, emacs_posix_spawn_init): New
helper functions.
(emacs_spawn): Use posix_spawn if possible.

Originally authored by: Philipp Stephani <phst@google.com>
---
 configure.ac   |  17 +++++
 src/callproc.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 210 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 33e7037afe..c231c2ceae 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4771,6 +4771,23 @@ AC_DEFUN
 dnl the current CFLAGS etc.
 AC_CHECK_FUNCS(snprintf)
 
+dnl posix_spawn.  The chdir and setsid functionality is relatively
+dnl recent, so we check for it specifically.
+AC_CHECK_HEADERS([spawn.h])
+AC_SUBST([HAVE_SPAWN_H])
+AC_CHECK_FUNCS([posix_spawn \
+                posix_spawn_file_actions_addchdir \
+                posix_spawn_file_actions_addchdir_np \
+                posix_spawnattr_setflags])
+AC_SUBST([HAVE_POSIX_SPAWN])
+AC_SUBST([HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR])
+AC_SUBST([HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NP])
+AC_SUBST([HAVE_POSIX_SPAWNATTR_SETFLAGS])
+AC_CHECK_DECLS([POSIX_SPAWN_SETSID], [], [], [[
+               #include <spawn.h>
+               ]])
+AC_SUBST([HAVE_DECL_POSIX_SPAWN_SETSID])
+
 dnl Check for glib.  This differs from other library checks in that
 dnl Emacs need not link to glib unless some other library is already
 dnl linking to glib.  Although glib provides no facilities that Emacs
diff --git a/src/callproc.c b/src/callproc.c
index fa43f97384..77590d99ae 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -28,6 +28,22 @@ Copyright (C) 1985-1988, 1993-1995, 1999-2021 Free Software Foundation,
 #include <sys/file.h>
 #include <fcntl.h>
 
+/* In order to be able to use `posix_spawn', it needs to support some
+   variant of `chdir' as well as `setsid'.  It is only enabled on
+   Darwin to work around vfork being deprecated.  */
+#if defined DARWIN_OS \
+  && defined HAVE_SPAWN_H && defined HAVE_POSIX_SPAWN        \
+  && defined HAVE_POSIX_SPAWNATTR_SETFLAGS                  \
+  && (defined HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR        \
+      || defined HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NP) \
+  && defined HAVE_DECL_POSIX_SPAWN_SETSID                   \
+  && HAVE_DECL_POSIX_SPAWN_SETSID == 1
+# include <spawn.h>
+# define USABLE_POSIX_SPAWN 1
+#else
+# define USABLE_POSIX_SPAWN 0
+#endif
+
 #include "lisp.h"
 
 #ifdef SETUP_SLAVE_PTY
@@ -1247,6 +1263,130 @@ child_setup (int in, int out, int err, char **new_argv, char **env,
 #endif  /* not WINDOWSNT */
 }
 
+#if USABLE_POSIX_SPAWN
+
+/* Set up ACTIONS and ATTRIBUTES for `posix_spawn'.  Return an error
+   number.  */
+
+static int
+emacs_posix_spawn_init_actions (posix_spawn_file_actions_t *actions,
+                                int std_in, int std_out, int std_err,
+                                const char *cwd)
+{
+  int error = posix_spawn_file_actions_init (actions);
+  if (error != 0)
+    return error;
+
+  error = posix_spawn_file_actions_adddup2 (actions, std_in,
+                                            STDIN_FILENO);
+  if (error != 0)
+    goto out;
+
+  error = posix_spawn_file_actions_adddup2 (actions, std_out,
+                                            STDOUT_FILENO);
+  if (error != 0)
+    goto out;
+
+  error = posix_spawn_file_actions_adddup2 (actions,
+                                            std_err < 0 ? std_out
+                                                        : std_err,
+                                            STDERR_FILENO);
+  if (error != 0)
+    goto out;
+
+  error =
+#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR
+    posix_spawn_file_actions_addchdir
+#else
+    posix_spawn_file_actions_addchdir_np
+#endif
+    (actions, cwd);
+  if (error != 0)
+    goto out;
+
+ out:
+  if (error != 0)
+    posix_spawn_file_actions_destroy (actions);
+  return error;
+}
+
+static int
+emacs_posix_spawn_init_attributes (posix_spawnattr_t *attributes)
+{
+  int error = posix_spawnattr_init (attributes);
+  if (error != 0)
+    return error;
+
+  error = posix_spawnattr_setflags (attributes,
+                                    POSIX_SPAWN_SETSID
+                                      | POSIX_SPAWN_SETSIGDEF
+                                      | POSIX_SPAWN_SETSIGMASK);
+  if (error != 0)
+    goto out;
+
+  sigset_t sigdefault;
+  sigemptyset (&sigdefault);
+
+#ifdef DARWIN_OS
+  /* Work around a macOS bug, where SIGCHLD is apparently
+     delivered to a vforked child instead of to its parent.  See:
+     https://lists.gnu.org/r/emacs-devel/2017-05/msg00342.html
+  */
+  sigaddset (&sigdefault, SIGCHLD);
+#endif
+
+  sigaddset (&sigdefault, SIGINT);
+  sigaddset (&sigdefault, SIGQUIT);
+#ifdef SIGPROF
+  sigaddset (&sigdefault, SIGPROF);
+#endif
+
+  /* Emacs ignores SIGPIPE, but the child should not.  */
+  sigaddset (&sigdefault, SIGPIPE);
+  /* Likewise for SIGPROF.  */
+#ifdef SIGPROF
+  sigaddset (&sigdefault, SIGPROF);
+#endif
+
+  error = posix_spawnattr_setsigdefault (attributes, &sigdefault);
+  if (error != 0)
+    goto out;
+
+  /* Stop blocking SIGCHLD in the child.  */
+  sigset_t oldset;
+  error = pthread_sigmask (SIG_SETMASK, NULL, &oldset);
+  if (error != 0)
+    goto out;
+  error = posix_spawnattr_setsigmask (attributes, &oldset);
+  if (error != 0)
+    goto out;
+
+ out:
+  if (error != 0)
+    posix_spawnattr_destroy (attributes);
+
+  return error;
+}
+
+static int
+emacs_posix_spawn_init (posix_spawn_file_actions_t *actions,
+                        posix_spawnattr_t *attributes, int std_in,
+                        int std_out, int std_err, const char *cwd)
+{
+  int error = emacs_posix_spawn_init_actions (actions, std_in,
+                                              std_out, std_err, cwd);
+  if (error != 0)
+    return error;
+
+  error = emacs_posix_spawn_init_attributes (attributes);
+  if (error != 0)
+    return error;
+
+  return 0;
+}
+
+#endif
+
 /* Start a new asynchronous subprocess.  If successful, return zero
    and store the process identifier of the new process in *NEWPID.
    Use STDIN, STDOUT, and STDERR as standard streams for the new
@@ -1266,10 +1406,58 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
              char **argv, char **envp, const char *cwd,
              const char *pty, const sigset_t *oldset)
 {
+#if USABLE_POSIX_SPAWN
+  /* Prefer the simpler `posix_spawn' if available.  `posix_spawn'
+     doesn't yet support setting up pseudoterminals, so we fall back
+     to `vfork' if we're supposed to use a pseudoterminal.  */
+
+  bool use_posix_spawn = pty == NULL;
+
+  posix_spawn_file_actions_t actions;
+  posix_spawnattr_t attributes;
+
+  if (use_posix_spawn)
+    {
+      /* Initialize optional attributes before blocking. */
+      int error
+        = emacs_posix_spawn_init (&actions, &attributes, std_in,
+                                  std_out, std_err, cwd);
+      if (error != 0)
+	return error;
+    }
+#endif
+
   int pid;
+  int vfork_error;
 
   eassert (input_blocked_p ());
 
+#if USABLE_POSIX_SPAWN
+  if (use_posix_spawn)
+    {
+      vfork_error = posix_spawn (&pid, argv[0], &actions, &attributes,
+                                 argv, envp);
+      if (vfork_error != 0)
+	pid = -1;
+
+      int error = posix_spawn_file_actions_destroy (&actions);
+      if (error != 0)
+	{
+	  errno = error;
+	  emacs_perror ("posix_spawn_file_actions_destroy");
+	}
+
+      error = posix_spawnattr_destroy (&attributes);
+      if (error != 0)
+	{
+	  errno = error;
+	  emacs_perror ("posix_spawnattr_destroy");
+	}
+
+      goto fork_done;
+    }
+#endif
+
 #ifndef WINDOWSNT
   /* vfork, and prevent local vars from being clobbered by the vfork.  */
   pid_t *volatile newpid_volatile = newpid;
@@ -1413,7 +1601,11 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
 
   /* Back in the parent process.  */
 
-  int vfork_error = pid < 0 ? errno : 0;
+  vfork_error = pid < 0 ? errno : 0;
+
+#if USABLE_POSIX_SPAWN
+ fork_done:
+#endif
 
   if (pid < 0)
     {
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 91+ messages in thread
* Re: master 2c79a8f 2/2: Use posix_spawn if possible.
@ 2020-12-25 13:16 Eli Zaretskii
  2020-12-26 11:26 ` Philipp Stephani
  0 siblings, 1 reply; 91+ messages in thread
From: Eli Zaretskii @ 2020-12-25 13:16 UTC (permalink / raw)
  To: Philipp Stephani; +Cc: emacs-devel

I'm sorry, but I reverted this commit and the previous one.  They
broke the MinGW build in fundamental ways, and I cannot afford having
the master branch broken so frequently, definitely not on weekends,
which are the only time I can work seriously on Emacs.

If you cannot make sure Emacs still builds on all supported platforms,
please either post your patches first, or push them to a scratch
branch, and ask people who have access to those platforms to test it
before the changes land on master.

Btw, regarding use of posix_spawn, I'd expect a discussion before we
make such a change.  AFAIU it is not a trivial decision, as
posix_spawn has its down sides, and therefore is not necessarily the
best API for running sub-processes on every supported platform, even
if you consider only the Posix ones.  We should consider the
advantages and disadvantages before we make the decision.

Thanks.



^ permalink raw reply	[flat|nested] 91+ messages in thread

end of thread, other threads:[~2022-04-19 17:32 UTC | newest]

Thread overview: 91+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-25  6:48 master 2c79a8f 2/2: Use posix_spawn if possible Saulius Menkevicius
2022-01-25  8:41 ` Eli Zaretskii
2022-01-25  8:58   ` Saulius Menkevicius
2022-01-25 11:46     ` Jostein Kjønigsen
2022-01-25 11:55       ` Po Lu
2022-01-25 12:22     ` Eli Zaretskii
2022-01-25 12:25       ` Saulius Menkevicius
2022-01-25 13:47         ` Eli Zaretskii
2022-01-28 17:12           ` Matt Armstrong
2022-01-29  8:03             ` Saulius Menkevičius
2022-01-29  8:26             ` Eli Zaretskii
2022-01-31 20:48               ` Saulius Menkevicius
2022-02-01  9:59                 ` Robert Pluim
2022-02-01 18:30                   ` Saulius Menkevicius
2022-02-01 19:23                     ` Robert Pluim
2022-02-01 19:52                       ` Eli Zaretskii
2022-02-02  8:30                         ` Robert Pluim
2022-02-02  8:54                           ` Saulius Menkevičius
2022-02-07 21:12                             ` Saulius Menkevicius
2022-02-08  8:27                               ` Robert Pluim
2022-02-08 12:12                               ` Eli Zaretskii
2022-02-08 12:18                                 ` Saulius Menkevicius
2022-02-08 14:59                                   ` Robert Pluim
2022-02-08 21:09                                     ` Saulius Menkevicius
2022-02-09  8:48                                       ` Robert Pluim
2022-02-12  8:44                                         ` Saulius Menkevicius
2022-02-12  8:59                                           ` Eli Zaretskii
2022-02-12  9:42                                             ` Saulius Menkevicius
2022-03-04  8:38                   ` [PATCH] posix_spawn blocks SIGCHLD in spawned processes (was: Re: master 2c79a8f 2/2: Use posix_spawn if possible.) Jürgen Hötzel
2022-03-04 10:07                     ` [PATCH] posix_spawn blocks SIGCHLD in spawned processes Robert Pluim
2022-03-04 15:41                       ` Jürgen Hötzel
2022-03-04 16:08                         ` Robert Pluim
2022-04-17 18:22                         ` Philipp Stephani
2022-04-19 14:36                           ` Robert Pluim
2022-04-19 14:48                             ` Philipp Stephani
2022-04-19 16:07                             ` Eli Zaretskii
2022-04-19 17:32                               ` Robert Pluim
2022-04-04 14:13                       ` Robert Pluim
2022-01-25 13:15 ` master 2c79a8f 2/2: Use posix_spawn if possible Stefan Monnier
  -- strict thread matches above, loose matches on Subject: below --
2021-11-08 11:00 Aaron Jensen
2021-11-08 11:03 ` Aaron Jensen
2021-11-08 19:37 ` Alan Third
2021-11-09 14:46 ` Philipp
2021-11-09 15:57   ` Aaron Jensen
2021-11-09 17:05     ` Eli Zaretskii
2021-11-09 18:12       ` Aaron Jensen
2021-11-12 11:48         ` Philipp
2021-11-12 13:42           ` Aaron Jensen
2021-11-12 22:05             ` Alan Third
2021-11-13 14:08               ` Aaron Jensen
2021-11-13 16:03                 ` Philipp
2021-11-13 16:17                   ` Aaron Jensen
2021-11-15 15:01           ` Dmitry Gutov
2020-12-25 13:16 Eli Zaretskii
2020-12-26 11:26 ` Philipp Stephani
2020-12-26 12:08   ` Eli Zaretskii
2020-12-26 12:16     ` Eli Zaretskii
2020-12-29 16:43       ` Philipp Stephani
2020-12-31 16:24         ` Philipp Stephani
2020-12-31 16:39           ` Eli Zaretskii
2020-12-31 17:36             ` Philipp Stephani
2020-12-31 17:47               ` Eli Zaretskii
2020-12-31 20:24                 ` Philipp Stephani
2020-12-31 20:36                   ` Eli Zaretskii
2021-01-01  7:59                     ` martin rudalics
2021-01-01  8:04                       ` Eli Zaretskii
2021-01-01 23:38           ` Andy Moreton
2021-01-01 23:56             ` Alan Third
2021-01-02  1:12               ` Andy Moreton
2021-01-02  6:53                 ` Eli Zaretskii
2021-01-02  8:56                   ` Andreas Schwab
2021-10-29  9:46                     ` YAMAMOTO Mitsuharu
2021-10-30 18:30                       ` Alan Third
2021-11-02 19:58                         ` Alan Third
2021-11-02 20:15                           ` Eli Zaretskii
2021-11-02 20:36                             ` Alan Third
2021-11-03  3:24                               ` Eli Zaretskii
2021-11-10 12:42                                 ` Philipp Stephani
2021-11-10 14:10                                   ` Eli Zaretskii
2021-11-11 17:52                                     ` Philipp
2021-11-11 18:00                                       ` Eli Zaretskii
2021-11-11 21:04                                         ` Philipp
2020-12-29 16:29     ` Philipp Stephani
2020-12-29 18:15       ` Eli Zaretskii
2020-12-29 21:36         ` Philipp Stephani
2020-12-30  3:33           ` Eli Zaretskii
2020-12-31 16:10             ` Philipp Stephani
2020-12-31 18:33               ` Eli Zaretskii
2020-12-31 17:50       ` Philipp Stephani
2020-12-31 18:34         ` Eli Zaretskii
2020-12-31 20:14           ` Philipp Stephani

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).