Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src/std/process.d: _spawnvp error handling is broken #10099

Open
dlangBugzillaToGithub opened this issue Nov 19, 2014 · 5 comments
Open

src/std/process.d: _spawnvp error handling is broken #10099

dlangBugzillaToGithub opened this issue Nov 19, 2014 · 5 comments

Comments

@dlangBugzillaToGithub
Copy link

danny.milo (@daym) reported this on 2014-11-19T21:33:14Z

Transfered from https://issues.dlang.org/show_bug.cgi?id=13753

CC List

Description

The _spawnvp in src/std/process.d is broken.

First, if the child process (say it has pid B) fails to execvp, it's a bad idea to then throw an Exception. The entire point of spawnvp in general is to hide the fact that the current process A was forked off. But now the Exception propagates through process B, so certainly the caller will notice that something is off (the caller is suddenly inside another process than he started out in). 

Later on, the waitpid result is not checked. It is possible for waitpid to return (-1). In that case, errno contains the error code and "status" contains garbage, which is then compared against.

Also, all Posix system calls can return (-1) and errno = EINTR (see <http://www.jwz.org/doc/worse-is-better.html>, search for "PC loser-ing") to indicate that while the user process asked for action S to be performed, really it should be checking and doing some other action T before.

So for the latter there really should be some global delegate that is called on EINTR which decides whether to do anything about it, possibly terminating the loop (or not, it depends). 

This is not specific to process.d but all functions that do system calls should call this. Even std.stdio.File functions should do this.

Also, it throws an Exception (literally that) using strerror_r to build it instead of just using ErrnoException. Why?

!!!There are attachements in the bugzilla issue that have not been copied over!!!

@dlangBugzillaToGithub
Copy link
Author

danny.milo commented on 2014-11-19T21:36:22Z

Created attachment 1454
Tests whether spawnvp magically forks processes for the caller

Tests whether spawnvp magically switches processes. Try with version(Posix) implementation of spawnvp.

@dlangBugzillaToGithub
Copy link
Author

danny.milo commented on 2014-11-19T21:56:03Z

Created attachment 1455
Patch to make _spawnvp less bad

checks waitpid() return value, does not magically put the caller into a new process. Does not properly handle EINTR.

@dlangBugzillaToGithub
Copy link
Author

danny.milo commented on 2014-11-19T22:00:46Z

See http://www.gnu.org/software/libc/manual/html_node/Interrupted-Primitives.html

@dlangBugzillaToGithub
Copy link
Author

danny.milo commented on 2014-11-25T18:25:13Z

Also, both the OSX and the Posix version of browse in the same file are broken in the same way...

@dlangBugzillaToGithub
Copy link
Author

bugzilla (@WalterBright) commented on 2019-12-10T10:27:22Z

spawnvp seems only to exist for windows now. But I did not check if this has been the case in 2014 too.

Tried to adapt the test for "browse":

```
import std.process;
import core.thread;

int main() {
        auto pidBefore = getpid();
        try {
                browse("DOESNOTEXIST");
                assert(false);
        } catch(Exception e) {
                auto pidAfterwards = getpid();
                assert(pidBefore == pidAfterwards); // make sure we are still in the same process
        }
        return 0;
}
```

This produces an Assertion failure (POSIX). And the process seems still to be running after the main process has stopped.

@LightBender LightBender removed the P3 label Dec 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants