Skip to content

Too many nested forkProcess's eventually cause SIGSEGV in the child

Original Haskell-cafe thread: https://groups.google.com/forum/#!msg/haskell-cafe/kHMsYRMcdPs/vWD9T7saCAAJ

Here is a slightly modified test program from that thread:

-- fork-bug.hs
import System.Environment (getArgs)
import System.Posix.Process (forkProcess)

fork_ 0 = putStrLn "Done forking"
fork_ n = forkProcess (fork_ (n - 1)) >> return ()

main = do
    [n] <- getArgs    
    fork_ (read n)

With n big enough the program doesn't print anything and crashes with SIGSEGV at (semi-)random places (the crash is somewhat hard to demonstrate from the shell):

$ ./fork-bug 100; sleep 0.1
Done forking
$ ./fork-bug 500; sleep 0.1
Done forking
$ ./fork-bug 1000; sleep 0.1
$

Looks like the problem lies in C-stack exhaustion in children - lowering the stack limit makes the crash happen much earlier:

$ (ulimit -s 128; ./fork-bug 5; sleep 0.1)
Done forking
$ (ulimit -s 128; ./fork-bug 6; sleep 0.1)
Done forking
$ (ulimit -s 128; ./fork-bug 7; sleep 0.1)
$ (ulimit -s 128; ./fork-bug 8; sleep 0.1)
$

Tracing with gdb shows that with each forkProcess the stack in the forked child goes deeper and deeper, although gdb shows call stacks of constant depth:

$ gdb -q fork-bug
Reading symbols from fork-bug...(no debugging symbols found)...done.
(gdb) set follow-fork-mode child
(gdb) break forkProcess
Breakpoint 1 at 0x470a60
(gdb) display $rsp
(gdb) run 3
Starting program: /tmp/fork-bug 3
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, 0x0000000000470a60 in forkProcess ()
1: $rsp = (void *) 0x7fffffff9e28
(gdb) bt
#0  0x0000000000470a60 in forkProcess ()
#1  0x0000000000406215 in s3sP_info ()
#2  0x0000000000000000 in ?? ()
(gdb) continue
Continuing.
[New process 20434]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[Switching to Thread 0x7ffff7fd5740 (LWP 20434)]

Breakpoint 1, 0x0000000000470a60 in forkProcess ()
1: $rsp = (void *) 0x7fffffff5d08
(gdb) bt
#0  0x0000000000470a60 in forkProcess ()
#1  0x0000000000406215 in s3sP_info ()
#2  0x0000000000000000 in ?? ()
(gdb) continue
Continuing.
[New process 20435]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[Switching to Thread 0x7ffff7fd5740 (LWP 20435)]

Breakpoint 1, 0x0000000000470a60 in forkProcess ()
1: $rsp = (void *) 0x7fffffff1be8
(gdb) bt
#0  0x0000000000470a60 in forkProcess ()
#1  0x0000000000406215 in s3sP_info ()
#2  0x0000000000000000 in ?? ()
(gdb) continue
Continuing.
[New process 20436]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Done forking
[Inferior 4 (process 20436) exited normally]

These results are from Ubuntu 14.04.4 with GHC 7.6.3, although OP reported using 7.10.3 and HEAD.

Trac metadata
Trac field Value
Version
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Runtime System
Test case
Differential revisions
BlockedBy
Related
Blocking
CC simonmar
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information