Skip to content

Commit 4da79d8

Browse files
authored
Refactor internal Crystal::System::Process#fork on UNIX (#16191)
The method now yields to let the caller do something in the child process after fork, rather than always compiling both paths (fork vs fork/exec) even though most applications only use the fork/exec path.
1 parent 1067f62 commit 4da79d8

File tree

1 file changed

+16
-12
lines changed

1 file changed

+16
-12
lines changed

src/crystal/system/unix/process.cr

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ struct Crystal::System::Process
187187
end
188188
{% end %}
189189

190-
def self.fork(*, will_exec = false)
190+
def self.fork(*, will_exec : Bool, &)
191191
newmask = uninitialized LibC::SigsetT
192192
oldmask = uninitialized LibC::SigsetT
193193

@@ -206,18 +206,16 @@ struct Crystal::System::Process
206206
when 0
207207
# child:
208208
pid = nil
209-
if will_exec
210-
# notify event loop
211-
Crystal::EventLoop.current.after_fork_before_exec
212209

213-
# reset signal handlers, then sigmask (inherited on exec):
214-
Crystal::System::Signal.after_fork_before_exec
210+
# after fork callback
211+
yield
212+
213+
if will_exec
214+
# reset sigmask (inherited on exec)
215215
LibC.sigemptyset(pointerof(newmask))
216216
LibC.pthread_sigmask(LibC::SIG_SETMASK, pointerof(newmask), nil)
217217
else
218-
{% unless flag?(:preview_mt) %}
219-
::Process.after_fork_child_callbacks.each(&.call)
220-
{% end %}
218+
# restore sigmask
221219
LibC.pthread_sigmask(LibC::SIG_SETMASK, pointerof(oldmask), nil)
222220
end
223221
when -1
@@ -239,9 +237,10 @@ struct Crystal::System::Process
239237
def self.fork(&)
240238
{% raise("Process fork is unsupported with multithreaded mode") if flag?(:preview_mt) %}
241239

242-
if pid = fork
243-
return pid
240+
pid = fork(will_exec: false) do
241+
::Process.after_fork_child_callbacks.each(&.call)
244242
end
243+
return pid if pid
245244

246245
begin
247246
yield
@@ -258,7 +257,12 @@ struct Crystal::System::Process
258257
def self.spawn(command_args, env, clear_env, input, output, error, chdir)
259258
r, w = FileDescriptor.system_pipe
260259

261-
pid = self.fork(will_exec: true)
260+
pid = fork(will_exec: true) do
261+
# notify event loop and reset signal handlers
262+
Crystal::EventLoop.current.after_fork_before_exec
263+
Crystal::System::Signal.after_fork_before_exec
264+
end
265+
262266
if !pid
263267
LibC.close(r)
264268
begin

0 commit comments

Comments
 (0)