Created attachment 1829
testcase
Actual result :
# ./test
foo done
foo done
foo done
Segmentation fault
Expected results :
foo done
...
main done
Comment #1 by alphaglosined — 2021-10-04T21:57:35Z
ldc's address sanitizer has some extra information:
foo done
foo done
AddressSanitizer:DEADLYSIGNAL
=================================================================
==28==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x55f694a96fd9 bp 0x7f791bdfecf0 sp 0x7f791bdfec70 T3)
==28==The signal is caused by a READ memory access.
==28==Hint: address points to the zero page.
#0 0x55f694a96fd9 in _d_dynamic_cast (/tmp/onlineapp-a6c082+0xebfd9)
#1 0x55f6949d73d0 in foo /sandbox/onlineapp.d:9:5
#2 0x7f791f50c608 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x9608)
#3 0x7f791f2c9292 in clone (/lib/x86_64-linux-gnu/libc.so.6+0x122292)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/tmp/onlineapp-a6c082+0xebfd9) in _d_dynamic_cast
Thread T3 created by T0 here:
#0 0x55f694a27eba in pthread_create /home/vsts/work/1/s/compiler-rt/lib/asan/asan_interceptors.cpp:214:3
#1 0x55f6949d7813 in _Dmain /sandbox/onlineapp.d:27:9
#2 0x55f694a9771b in _D2rt6dmain212_d_run_main2UAAamPUQgZiZ6runAllMFZv (/tmp/onlineapp-a6c082+0xec71b)
#3 0x55f694a9746d in _d_run_main (/tmp/onlineapp-a6c082+0xec46d)
#4 0x55f6949d7924 in main /dlang/ldc-1.26.0/bin/../import/core/internal/entrypoint.d:42:17
#5 0x7f791f1ce0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
==28==ABORTING
Error: /tmp/onlineapp-a6c082 failed with status: 1
Looks like something inside of thread_attachThis is doing a cast and not checking for null.
Comment #2 by acehreli — 2021-10-05T07:43:46Z
This is likely the same as 18063.
Comment #3 by thomas.bockman — 2021-10-05T20:36:50Z
It appears to be a race condition between `thread_attachThis` and `GC.collect`. Serializing them prevents the crash:
//////////////////////////////////////////////////
import core.sys.posix.pthread;
import core.memory;
import core.sync.mutex;
import core.thread;
import std.stdio;
enum allocCount = 1000;
enum allocSize = 1000;
enum threadCount = 100;
enum collectCount = 1000;
shared Mutex serialize;
shared static this() {
serialize = new shared Mutex;
}
extern(C) void* foo(void*)
{
serialize.lock_nothrow();
thread_attachThis();
serialize.unlock_nothrow();
scope(exit)
thread_detachThis();
foreach(_; 0..allocCount) {
new int;
new int[allocSize];
}
writeln(`foo done`);
return null;
}
void main()
{
pthread_t thread;
foreach(_; 0..threadCount) {
auto status = pthread_create(&thread, null, &foo, null);
assert(status == 0);
foreach(i; 0..collectCount) {
serialize.lock_nothrow();
GC.collect();
serialize.unlock_nothrow();
}
pthread_join(thread, null);
}
writeln(`main done`);
}
//////////////////////////////////////////////////
Comment #4 by robert.schadek — 2024-12-07T13:41:24Z