Bug 20227 – "Aborting from src/core/sync/event.d(141) Error: pthread_mutex_destroy failed." after fork()
Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P4
Component
druntime
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2019-09-18T15:00:58Z
Last change time
2019-09-27T06:01:19Z
Keywords
pull
Assigned to
No Owner
Creator
Vladimir Panteleev
Comments
Comment #0 by dlang-bugzilla — 2019-09-18T15:00:58Z
/////////////////////////// test.d //////////////////////////
import core.memory;
import core.stdc.stdio;
import core.sys.posix.sys.wait;
import core.sys.posix.unistd;
void main()
{
printf("[parent] Creating garbage...\n");
foreach (n; 0 .. 1_000)
new uint[1_000_000];
printf("[parent] Collecting garbage...\n");
GC.collect();
printf("[parent] Forking...\n");
auto i = fork();
if (i < 0)
assert(false, "Fork failed");
if (i == 0)
{
printf("[child] In fork.\n");
printf("[child] Creating garbage...\n");
foreach (n; 0 .. 1_000)
new uint[1_000_000];
printf("[child] Collecting garbage...\n");
GC.collect();
printf("[child] Exiting fork.\n");
}
else
{
printf("[parent] Waiting for fork (PID %d).\n", i);
int status;
i = waitpid(i, &status, 0);
printf("[parent] Fork %d exited (%d).\n", i, status);
}
}
/////////////////////////////////////////////////////////////
The program produces this output:
[parent] Creating garbage...
[parent] Collecting garbage...
[parent] Forking...
[parent] Waiting for fork (PID 19784).
[child] In fork.
[child] Creating garbage...
[child] Collecting garbage...
[child] Exiting fork.
Aborting from src/core/sync/event.d(141) Error: pthread_mutex_destroy failed.[parent] Fork 19784 exited (134).
I'm not sure what exactly happens, but my best guess is:
1. GC creates worker threads
2. Program forks, leaving the worker threads behind
3. The GC keeps working, though, without any worker threads to read from its queue, it does all the work in the main thread
4. On exit, the GC fails to destroy thread-related resources as it is not aware that the program has forked.
Comment #1 by r.sagitario — 2019-09-18T20:42:58Z
> 1. GC creates worker threads
> 2. Program forks, leaving the worker threads behind
> 3. The GC keeps working, though, without any worker threads to read
> from its queue, it does all the work in the main thread
That's about what I expected to happen. If the parent process hasn't started any collection, the fork will create its own set of scan threads.
> 4. On exit, the GC fails to destroy thread-related resources as
> it is not aware that the program has forked.
I didn't think of this. I wonder why the existing tests (e.g. in std.stdio) didn't fail, maybe because they didn't start any collection before forking.
I guess what needs to happen is to reinitialize thread handles and used mutices in an atfork child handler.
Comment #2 by r.sagitario — 2019-09-19T04:34:05Z
I just tried to reproduce the issue with dmd 2.088 in an Ubuntu 19 VM, but it passes without the error message. What kind of system do you use? Does it need some specific compile options?
Comment #3 by dlang-bugzilla — 2019-09-19T04:38:50Z
I can reproduce this issue on my home machine (Arch Linux x86_64, i7-4960X) and my server (Ubuntu Server 16.04 x86_64, i7-7700). If it helps, I can get you an ssh account on the server.
Comment #4 by dlang-bot — 2019-09-20T14:20:10Z
@rainers created dlang/druntime pull request #2805 "fix Issue 20227 - "Error: phread_mutex_destroy failed." after fork()" fixing this issue:
- fix Issue 20227 - "Aborting from src/core/sync/event.d(141) Error: pthread_mutex_destroy failed." after fork()
clear thread handles and events for parallel marking in child process after fork
https://github.com/dlang/druntime/pull/2805
Comment #5 by dlang-bot — 2019-09-27T06:01:19Z
dlang/druntime pull request #2805 "fix Issue 20227 - "Error: phread_mutex_destroy failed." after fork()" was merged into stable:
- e59c057c6c50f919131da5e508488be01de9cb05 by Rainer Schuetze:
fix Issue 20227 - "Aborting from src/core/sync/event.d(141) Error: pthread_mutex_destroy failed." after fork()
clear thread handles and events for parallel marking in child process after fork
https://github.com/dlang/druntime/pull/2805