Skip to content

Commit 5ae986d

Browse files
CyberShadowthewilsonator
authored andcommitted
std.process: Retry interrupted syscalls when creating processes
Fixes #10884
1 parent 9dba43a commit 5ae986d

File tree

1 file changed

+14
-3
lines changed

1 file changed

+14
-3
lines changed

std/process.d

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,8 +1247,19 @@ private Pid spawnProcessPosix(scope const(char[])[] args,
12471247
else
12481248
{
12491249
closePipeWriteEnds();
1250+
1251+
T retryInterrupted(T)(scope T delegate() syscall)
1252+
{
1253+
import core.stdc.errno : errno, EINTR;
1254+
T result;
1255+
do
1256+
result = syscall();
1257+
while (result == -1 && .errno == EINTR);
1258+
return result;
1259+
}
1260+
12501261
auto status = InternalError.noerror;
1251-
auto readExecResult = core.sys.posix.unistd.read(forkPipe[0], &status, status.sizeof);
1262+
auto readExecResult = retryInterrupted(() => core.sys.posix.unistd.read(forkPipe[0], &status, status.sizeof));
12521263
// Save error number just in case if subsequent "waitpid" fails and overrides errno
12531264
immutable lastError = .errno;
12541265

@@ -1257,7 +1268,7 @@ private Pid spawnProcessPosix(scope const(char[])[] args,
12571268
// Forked child exits right after creating second fork. So it should be safe to wait here.
12581269
import core.sys.posix.sys.wait : waitpid;
12591270
int waitResult;
1260-
waitpid(id, &waitResult, 0);
1271+
retryInterrupted(() => waitpid(id, &waitResult, 0));
12611272
}
12621273

12631274
if (readExecResult == -1)
@@ -1267,7 +1278,7 @@ private Pid spawnProcessPosix(scope const(char[])[] args,
12671278
if (status != InternalError.noerror)
12681279
{
12691280
int error;
1270-
readExecResult = read(forkPipe[0], &error, error.sizeof);
1281+
readExecResult = retryInterrupted(() => read(forkPipe[0], &error, error.sizeof));
12711282
string errorMsg;
12721283
final switch (status)
12731284
{

0 commit comments

Comments
 (0)