I got the following kernel panic when running a program that repeatedly fork()s new processes:
425.338 [#0 ResourceGraph.Applet(31:31)]: test-fork-crash(3262) resident:436, shared:436, virtual:3075
425.338 [#0 ResourceGraph.Applet(31:31)]: Shell(40) resident:825, shared:825, virtual:2656
425.338 [#0 ResourceGraph.Applet(31:31)]: LaunchServer(39) resident:1452, shared:1452, virtual:4717
425.338 [#0 ResourceGraph.Applet(31:31)]: ClipboardHistory.Applet(37) resident:1681, shared:1681, virtual:7263
425.338 [#0 ResourceGraph.Applet(31:31)]: Terminal(36) resident:4362, shared:4362, virtual:9964
425.338 [#0 ResourceGraph.Applet(31:31)]: Clipboard(35) resident:456, shared:456, virtual:2101
425.338 [#0 ResourceGraph.Applet(31:31)]: Taskbar(34) resident:2741, shared:2741, virtual:8747
425.338 [#0 ResourceGraph.Applet(31:31)]: CrashDaemon(33) resident:578, shared:578, virtual:2429
425.338 [#0 ResourceGraph.Applet(31:31)]: Audio.Applet(32) resident:1704, shared:1704, virtual:7446
425.338 [#0 ResourceGraph.Applet(31:31)]: ResourceGraph.Applet(31) resident:1654, shared:1654, virtual:7239
425.338 [#0 ResourceGraph.Applet(31:31)]: FileManager (Desktop)(30) resident:3863, shared:3863, virtual:9860
425.338 [#0 ResourceGraph.Applet(31:31)]: Keymap.Applet(29) resident:1648, shared:1648, virtual:7242
425.338 [#0 ResourceGraph.Applet(31:31)]: ConfigServer(28) resident:558, shared:558, virtual:2258
425.338 [#0 ResourceGraph.Applet(31:31)]: WorkspacePicker.Applet(27) resident:1641, shared:1641, virtual:7235
425.338 [#0 ResourceGraph.Applet(31:31)]: AudioServer(26) resident:490, shared:490, virtual:3190
425.338 [#0 ResourceGraph.Applet(31:31)]: Network.Applet(24) resident:1653, shared:1653, virtual:7251
425.338 [#0 ResourceGraph.Applet(31:31)]: SystemServer(23) resident:472, shared:472, virtual:2145
425.338 [#0 ResourceGraph.Applet(31:31)]: DHCPClient(22) resident:439, shared:439, virtual:2097
425.338 [#0 ResourceGraph.Applet(31:31)]: Clipboard(15) resident:454, shared:454, virtual:2101
425.338 [#0 ResourceGraph.Applet(31:31)]: LookupServer(14) resident:490, shared:490, virtual:2160
425.338 [#0 ResourceGraph.Applet(31:31)]: LoginServer(13) resident:1768, shared:1768, virtual:7347
425.338 [#0 ResourceGraph.Applet(31:31)]: WindowServer(12) resident:6390, shared:6390, virtual:11171
425.338 [#0 ResourceGraph.Applet(31:31)]: DeviceMapper(11) resident:436, shared:436, virtual:2053
425.338 [#0 ResourceGraph.Applet(31:31)]: Network Task(9) resident:0, shared:0, virtual:0
425.338 [#0 ResourceGraph.Applet(31:31)]: SystemServer(8) resident:466, shared:466, virtual:2129
425.338 [#0 ResourceGraph.Applet(31:31)]: UHCI Hot Plug Task(7) resident:0, shared:0, virtual:0
425.338 [#0 ResourceGraph.Applet(31:31)]: UHCI Async Poll Task(6) resident:0, shared:0, virtual:0
425.338 [#0 ResourceGraph.Applet(31:31)]: Finalizer Task(5) resident:0, shared:0, virtual:0
425.338 [#0 ResourceGraph.Applet(31:31)]: VFS Sync Task(4) resident:0, shared:0, virtual:0
425.338 [#0 ResourceGraph.Applet(31:31)]: ATA WorkQueue Task(3) resident:0, shared:0, virtual:0
425.338 [#0 ResourceGraph.Applet(31:31)]: IO WorkQueue Task(2) resident:0, shared:0, virtual:0
426.141 [#0 ResourceGraph.Applet(31:31)]: SysFS: Could not refresh contents: Error(errno=12)
426.141 [#0 ResourceGraph.Applet(31:31)]: MM: Unable to commit 1024 pages, have only 19
[Finalizer Task(5:5)]: ASSERTION FAILED: m_thread_did_exit
[Finalizer Task(5:5)]: ././Kernel/Tasks/Thread.h:1117 in void* Kernel::Thread::JoinBlockerSet::exit_value() const
[Finalizer Task(5:5)]: KERNEL PANIC! :^(
[Finalizer Task(5:5)]: Aborted
[Finalizer Task(5:5)]: at ./Kernel/Arch/x86_64/CPU.cpp:36 in void abort()
[Finalizer Task(5:5)]: Kernel + 0x000000000096412a Kernel::__panic(char const*, unsigned int, char const*) +0x9a
[Finalizer Task(5:5)]: Kernel + 0x0000000000ea2d06 abort +0x22e
[Finalizer Task(5:5)]: Kernel + 0x0000000000ea2ad8 abort +0x0
[Finalizer Task(5:5)]: Kernel + 0x0000000000dd5d2f bool Kernel::Thread::BlockerSet::unblock_all_blockers_whose_conditions_are_met_locked<Kernel::Thread::JoinBlockerSet::do_unblock_joiner()::{lambda(Kernel::Thread::Blocker&, void*, bool&)#1}>(Kernel::Thread::JoinBlockerSet::do_unblock_joiner()::{lambda(Kernel::Thread::Blocker&, void*, bool&)#1}) [clone .isra.0] +0x41f
[Finalizer Task(5:5)]: Kernel + 0x0000000000dfb8b8 Kernel::Thread::finalize() +0x228
[Finalizer Task(5:5)]: Kernel + 0x0000000000dfca09 Kernel::Thread::finalize_dying_threads() +0xaf9
[Finalizer Task(5:5)]: Kernel + 0x0000000000d4309b Kernel::finalizer_task(void*) +0x1db
You can reproduce this by applying the following diff and running test-fork-crash
from the shell.
Note that the crash takes a minute or two to happen, and it doesn't happen 100% of the time you run the program.
diff --git a/Userland/Utilities/CMakeLists.txt b/Userland/Utilities/CMakeLists.txt
index 7f86cfee06..bb5f27b131 100644
--- a/Userland/Utilities/CMakeLists.txt
+++ b/Userland/Utilities/CMakeLists.txt
@@ -155,6 +155,7 @@ target_link_libraries(telws PRIVATE LibProtocol LibLine LibURL)
target_link_libraries(test-imap PRIVATE LibIMAP)
target_link_libraries(test-jpeg-roundtrip PRIVATE LibGfx)
target_link_libraries(test-pthread PRIVATE LibThreading)
+target_link_libraries(test-fork-crash PRIVATE LibThreading)
target_link_libraries(touch PRIVATE LibFileSystem)
target_link_libraries(unzip PRIVATE LibArchive LibCompress LibCrypto LibFileSystem)
target_link_libraries(update-cpp-test-results PRIVATE LibCpp)
diff --git a/Userland/Utilities/test-fork-crash.cpp b/Userland/Utilities/test-fork-crash.cpp
new file mode 100644
index 0000000000..1e68517606
--- /dev/null
+++ b/Userland/Utilities/test-fork-crash.cpp
@@ -0,0 +1,36 @@
+#include <AK/Assertions.h>
+#include <LibMain/Main.h>
+#include <LibThreading/Thread.h>
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+ErrorOr<int> serenity_main(Main::Arguments)
+{
+ NonnullRefPtr<Threading::Thread> forker_thread = TRY(Threading::Thread::try_create([&]() {
+ while(true) {
+ usleep(100);
+ pid_t pid = fork();
+ printf("forked\n");
+ switch(pid) {
+ case -1:
+ perror(nullptr);
+ exit(1);
+ case 0:
+ usleep(100);
+ exit(0);
+ default:
+ break;
+ }
+ }
+ return 0;
+ }));
+
+ forker_thread->start();
+ auto result = forker_thread->join();
+
+ return 0;
+}
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too