From f5dc5ea66cc6c396359c37c7c4193066c996ba27 Mon Sep 17 00:00:00 2001
From: Cyrill Gorcunov <gorcunov@gmail.com>
Date: Mon, 2 Mar 2020 19:43:22 +0300
Subject: [PATCH] popen: handle sid on macos

Due to os specifics we can't call setsid after vfork on macos
(vfork is not longer a part of posix btw). Instead we can use
ioctl to clear the session, then initiate a new process group.

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
---
 src/lib/core/popen.c | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/src/lib/core/popen.c b/src/lib/core/popen.c
index 6e5ca21bd9..a0630e3d90 100644
--- a/src/lib/core/popen.c
+++ b/src/lib/core/popen.c
@@ -16,6 +16,10 @@
 #include "coio.h"
 #include "say.h"
 
+#ifdef TARGET_OS_DARWIN
+# include <sys/ioctl.h>
+#endif
+
 /* A mapping to find popens by their pids in a signal handler */
 static struct mh_i32ptr_t *popen_pids_map = NULL;
 
@@ -833,15 +837,29 @@ popen_new(struct popen_opts *opts)
 		if (opts->flags & POPEN_FLAG_RESTORE_SIGNALS)
 			signal_reset();
 
-		/*
-		 * We have to be a session leader otherwise
-		 * won't be able to kill a group of children.
-		 */
 		if (opts->flags & POPEN_FLAG_SETSID) {
+#ifndef TARGET_OS_DARWIN
 			if (setsid() == -1) {
 				say_syserror("child: setsid failed");
 				goto exit_child;
 			}
+#else
+			/*
+			 * Note that on MacOS we're not allowed to
+			 * set sid after vfork (it is OS specific)
+			 * thus use ioctl instead.
+			 */
+			int ttyfd = open("/dev/tty", O_RDWR, 0);
+			if (ttyfd >= 0) {
+				ioctl(ttyfd, TIOCNOTTY, 0);
+				close(ttyfd);
+			}
+
+			if (setpgrp() == -1) {
+				say_syserror("child: setpgrp failed");
+				goto exit_child;
+			}
+#endif
 		}
 
 		if (opts->flags & POPEN_FLAG_CLOSE_FDS) {
-- 
GitLab