[Tarantool-patches] [PATCH 6/7] popen: handle setsid os specifics

Alexander Turenko alexander.turenko at tarantool.org
Tue Mar 10 18:49:49 MSK 2020


On Tue, Mar 03, 2020 at 02:45:37PM +0300, Cyrill Gorcunov wrote:
> On Tue, Mar 03, 2020 at 02:38:53PM +0300, Alexander Turenko wrote:
> > On Mon, Mar 02, 2020 at 11:12:26PM +0300, Cyrill Gorcunov wrote:
> > > On linux it is fine to call setsid right after
> > > the vfork, in turn on bsd pgrp should be used.
> > 
> > Can you refer a source of this information?
> > 
> > I tried the following snippet on Mac OS and FreeBSD and it at least does
> > not report an error:
> > 
> >  | #include <unistd.h>
> >  | #include <stdio.h>
> >  | 
> >  | int
> >  | main()
> >  | {
> >  | 	if (setsid() == -1) {
> >  | 		perror("setsid");
> >  | 		return 1;
> >  | 	}
> >  | 	return 0;
> >  | }
> > 
> > $ cc setsid.c -o setsid
> > $ echo 1 | ./setsid
> > 
> > (Pipeline is to not be a session leader already, this will lead to EPERM.)
> 
> I found that people are hitting the same problem.
> https://stackoverflow.com/questions/15179361/setpgrp-setpgid-fails-works-on-mac-osx-not-on-linux
> 
> The main problem is that I don't have a clue about macos internals
> but it looks like we have to setup group instead. To me it is
> vague area. I suspect it is due to vfork macos specifics.

We discussed this with Cyrill and the result is the following.

setsid() actually does not work on Mac OS after vfork() (however works
after fork()):

 | #include <sys/types.h>
 | #include <sys/wait.h>
 | #include <unistd.h>
 | #include <stdio.h>
 | 
 | int
 | main()
 | {
 | 	pid_t pid;
 | 	if ((pid = vfork()) == 0) {
 | 		/* Child. */
 | 		if (setsid() == -1) {
 | 			perror("setsid");
 | 			_exit(1);
 | 		}
 | 		_exit(0);
 | 	}
 | 	/* Parent. */
 | 	int status;
 | 	waitpid(pid, &status, 0);
 | 	return 0;
 | }

Compile and run it on Mac OS:

 | $ cc vfork_setsid.c -o vfork_setsid
 | $ ./vfork_setsid
 | setsid: Operation not permitted

It seems that setsid() is used mainly to disassociate from a controlling
terminal (to don't be hit by SIGHUP if it'll die). In this context
setpgrp() would not be sufficient.

I found that it is possible to use ioctl(<tty fd>, TIOCNOTTY, 0) to
disassociate from a controlling terminal. It will not move a child
process to the new session, but it seems that just don't being hit by
SIGHUP is everything that a user want.

So I would pick up this way as the workaround.

My sources:

[1]: https://github.com/emacs-mirror/emacs/commit/a13eaddce2ddbe3ba0b7f4c81715bc0fcdba99f6
[2]: https://github.com/emacs-mirror/emacs/commit/9cd23a29147acb86c860ce11febe24cf837f3f8a
[3]: http://man7.org/linux/man-pages/man4/tty.4.html
[4]: https://stackoverflow.com/a/8777697/1598057
[5]: https://reviews.freebsd.org/D22572

Cyrill already sent the fix, but I decided to summarize our discussion
anyway.

WBR, Alexander Turenko.


More information about the Tarantool-patches mailing list