@@ -59,41 +59,25 @@ struct Crystal::System::Process
5959 end
6060
6161 private def self.fork_for_exec
62- newmask = uninitialized LibC ::SigsetT
63- oldmask = uninitialized LibC ::SigsetT
64-
65- # block signals while we fork, so the child process won't forward signals it
66- # may receive to the parent through the signal pipe, but make sure to not
67- # block stop-the-world signals as it appears to create deadlocks in glibc
68- # for example; this is safe because these signal handlers musn't be
69- # registered through `Signal.trap` but directly through `sigaction`.
70- LibC .sigfillset(pointerof (newmask))
71- LibC .sigdelset(pointerof (newmask), System ::Thread .sig_suspend)
72- LibC .sigdelset(pointerof (newmask), System ::Thread .sig_resume)
73- ret = LibC .pthread_sigmask(LibC ::SIG_SETMASK , pointerof (newmask), pointerof (oldmask))
74- raise RuntimeError .from_errno(" Failed to disable signals" ) unless ret == 0
62+ block_signals do |sigmask |
63+ case pid = lock_write { LibC .fork }
64+ when 0
65+ # forked process
7566
76- case pid = lock_write { LibC .fork }
77- when 0
78- # child:
79- pid = nil
67+ Crystal ::System ::Signal .after_fork_before_exec
8068
81- Crystal ::System ::Signal .after_fork_before_exec
69+ # reset sigmask (inherited on exec)
70+ LibC .sigemptyset(sigmask)
8271
83- # reset sigmask (inherited on exec)
84- LibC .sigemptyset(pointerof (newmask))
85- LibC .pthread_sigmask(LibC ::SIG_SETMASK , pointerof (newmask), nil )
86- when -1
87- # error:
88- errno = Errno .value
89- LibC .pthread_sigmask(LibC ::SIG_SETMASK , pointerof (oldmask), nil )
90- raise RuntimeError .from_os_error(" fork" , errno)
91- else
92- # parent:
93- LibC .pthread_sigmask(LibC ::SIG_SETMASK , pointerof (oldmask), nil )
72+ nil
73+ when -1
74+ # forking process: error
75+ raise RuntimeError .from_errno(" fork" )
76+ else
77+ # forking process: success
78+ pid
79+ end
9480 end
95-
96- pid
9781 end
9882
9983 # This method is similar to `.replace` (used for `Process.exec`) with some
0 commit comments