Recommended posix_spawnattr_t for NSTask's implementation


(Dan Stenmark) #1

I hope to take a crack at implementing some of NSTask this weekend. What are the recommended posix_spawnattr_t flags that should be set? Do we also want to take the opportunity to expose the ability to override some of these flags (like POSIX_SPAWN_SETPGROUP) or do we want to avoid tying this with posix_spawn() too closely?

Dan


(Philippe Hausler) #2

I would definitely say that posix_spawn is the correct path to implement this; that will keep pretty close to the way the one on darwin works;

Couple of suggestions:

posix_spawnattr_setsigmask should be set to the empty signal set

the attribute flags should probably be POSIX_SPAWN_CLOEXEC_DEFAULT | POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF

You can probably skip QoS since it won’t exist on linux.

There may be some issue with not having libdispatch to use for a source to watch a DISPATCH_PROC_EXIT but this perhaps could be done via a pthread (not certain on exactly how but perhaps it can be done)

It also might be useful in this case to drop down to C similarly as CFXMLInterface - but pick your poison on that one.

···

On Dec 18, 2015, at 11:08 AM, Dan Stenmark via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

I hope to take a crack at implementing some of NSTask this weekend. What are the recommended posix_spawnattr_t flags that should be set? Do we also want to take the opportunity to expose the ability to override some of these flags (like POSIX_SPAWN_SETPGROUP) or do we want to avoid tying this with posix_spawn() too closely?

Dan
_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


(David Smith) #3

One issue that we ran into in the ObjC NSTask is setting the current working directory in the child process. We worked around the lack of an API for that by using per-thread working directories, which is kind of awful. I'm not up to date on what the best approach to use for this on Linux would be; it sounds like clone() can do it, but I don't know if that's exposed at the posix_spawn level at all.

  David

···

On Dec 18, 2015, at 11:08 AM, Dan Stenmark via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

I hope to take a crack at implementing some of NSTask this weekend. What are the recommended posix_spawnattr_t flags that should be set? Do we also want to take the opportunity to expose the ability to override some of these flags (like POSIX_SPAWN_SETPGROUP) or do we want to avoid tying this with posix_spawn() too closely?

Dan
_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


(Pierre Habouzit) #4

-Pierre

I would definitely say that posix_spawn is the correct path to implement this; that will keep pretty close to the way the one on darwin works;

Couple of suggestions:

posix_spawnattr_setsigmask should be set to the empty signal set

the attribute flags should probably be POSIX_SPAWN_CLOEXEC_DEFAULT | POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF

You can probably skip QoS since it won’t exist on linux.

There may be some issue with not having libdispatch to use for a source to watch a DISPATCH_PROC_EXIT but this perhaps could be done via a pthread (not certain on exactly how but perhaps it can be done)

No, it can’t that’s the big problem with posix_spawn() on linux, because the new task isn’t a child with this (or maybe it is on linux I don’t know) and there is no equivalent to the EVFILT_PROC which is the kevent backend for the PROC_EXIT dispatch source thing.

This feature is only available through netlink on linux which is restricted to the root user.

It *may* be that posix_spawn()ed things are children on linux and that a SIGCHLD source should be used instead, which means that NSTask would have to multiplex the SIGCHLD + waitpid() and route them back to the right NSTask().

···

On Dec 18, 2015, at 11:14 AM, Philippe Hausler via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

It also might be useful in this case to drop down to C similarly as CFXMLInterface - but pick your poison on that one.

On Dec 18, 2015, at 11:08 AM, Dan Stenmark via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

I hope to take a crack at implementing some of NSTask this weekend. What are the recommended posix_spawnattr_t flags that should be set? Do we also want to take the opportunity to expose the ability to override some of these flags (like POSIX_SPAWN_SETPGROUP) or do we want to avoid tying this with posix_spawn() too closely?

Dan
_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev

_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


(Pierre Habouzit) #5

FWIW Glibc implements posix_spawn on posix platforms in terms of {,v}fork + execve.
So that means that SIGCHLD can be used.

I don’t think linux has per-thread wd, since linux has had atcalls for a very long time, which makes this system interface not useful and only weird (pthread_{,f}chdir).

I don’t think there’s a good way to fix this beside asking for POSIX to have a posix_spawnattr_setwd(attr, const char *); or changing it around the spawn, which of course, is bad and racy

The other alternative is to use a trampoline execv() when -[NSTask currentDirectoryPath] has been set that will just chdir() and exec's again. it’s not really pretty but does the job. Given that this should be the exception and not the rule, maybe that’s acceptable.

-Pierre

···

On Dec 18, 2015, at 11:37 AM, David Smith via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

One issue that we ran into in the ObjC NSTask is setting the current working directory in the child process. We worked around the lack of an API for that by using per-thread working directories, which is kind of awful. I'm not up to date on what the best approach to use for this on Linux would be; it sounds like clone() can do it, but I don't know if that's exposed at the posix_spawn level at all.

  David

On Dec 18, 2015, at 11:08 AM, Dan Stenmark via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

I hope to take a crack at implementing some of NSTask this weekend. What are the recommended posix_spawnattr_t flags that should be set? Do we also want to take the opportunity to expose the ability to override some of these flags (like POSIX_SPAWN_SETPGROUP) or do we want to avoid tying this with posix_spawn() too closely?

Dan
_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev

_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev


(Dan Stenmark) #6

I’m assuming that OS X’s method for setting a pthread’s cwd is private API. Unless a better way to accomplish the same end-goal is in the works, is there any way to expose it?

In regards to Linux, the more I look at this, the less attractive posix_spawn() appears as a way of implementing this on that platform. I’ll likely have a better idea how to approach this following some prototyping later tonight, but my current line of thinking involves vfork() -> unshare() -> chdir() -> execve().

Dan

···

On Dec 18, 2015, at 12:39 PM, Pierre Habouzit <pierre@habouzit.net> wrote:

FWIW Glibc implements posix_spawn on posix platforms in terms of {,v}fork + execve.
So that means that SIGCHLD can be used.

I don’t think linux has per-thread wd, since linux has had atcalls for a very long time, which makes this system interface not useful and only weird (pthread_{,f}chdir).

I don’t think there’s a good way to fix this beside asking for POSIX to have a posix_spawnattr_setwd(attr, const char *); or changing it around the spawn, which of course, is bad and racy

The other alternative is to use a trampoline execv() when -[NSTask currentDirectoryPath] has been set that will just chdir() and exec's again. it’s not really pretty but does the job. Given that this should be the exception and not the rule, maybe that’s acceptable.

-Pierre

On Dec 18, 2015, at 11:37 AM, David Smith via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

One issue that we ran into in the ObjC NSTask is setting the current working directory in the child process. We worked around the lack of an API for that by using per-thread working directories, which is kind of awful. I'm not up to date on what the best approach to use for this on Linux would be; it sounds like clone() can do it, but I don't know if that's exposed at the posix_spawn level at all.

  David

On Dec 18, 2015, at 11:08 AM, Dan Stenmark via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

I hope to take a crack at implementing some of NSTask this weekend. What are the recommended posix_spawnattr_t flags that should be set? Do we also want to take the opportunity to expose the ability to override some of these flags (like POSIX_SPAWN_SETPGROUP) or do we want to avoid tying this with posix_spawn() too closely?

Dan
_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev

_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev