I'm trying this little example, with the help of the async gem on ruby 3.1.3p185 on linux:
require 'async'
require 'proc/wait3'
Async do |tsk|
pid = fork { sleep 2; exit! 2 }
p Time.now
t2 = tsk.async { Process.wait4 pid }
p Time.now
t2.wait
p Time.now
end
I'd expect the first two p Time.now to print roughly the same time, then the third one two seconds later, but instead I get
2023-02-22 20:24:36.639229529 +0100
2023-02-22 20:24:38.641093571 +0100
2023-02-22 20:24:38.641145659 +0100
If I replace Process.wait4 with Process.wait, it works, but of course I don't get the resource usage stats that way.
I've tried to workaround this problem by putting the wait4 call into a different thread, but that didn't work either since this gem doesn't release the GVL while calling wait4 and friends.
...Actually, I'm not sure whether this can be solved at all, both non-blocking fibers and the process handling in ruby is a mess. Fiber::Scheduler is a monolithic piece, I think you'd need to add new methods here to support wait3/wait4, then update all Fiber::Scheduler implementations. Not likely to happen without having official support for wait3/wait4 in ruby.
Process handling is also a mess, sometimes it registers a SIGCHLD handler and uses that instead of waitpid, and bad things can happen if you fork/wait behind process.c's back. (Once I tried to write some code that calls clone on Linux. Half of the stuff you're supposed to call when forking is not exposed from libruby, and if you don't call them, you'll have random deadlocks later.)
I'm trying this little example, with the help of the async gem on ruby 3.1.3p185 on linux:
I'd expect the first two
p Time.nowto print roughly the same time, then the third one two seconds later, but instead I getIf I replace
Process.wait4withProcess.wait, it works, but of course I don't get the resource usage stats that way.I've tried to workaround this problem by putting the
wait4call into a different thread, but that didn't work either since this gem doesn't release the GVL while callingwait4and friends....Actually, I'm not sure whether this can be solved at all, both non-blocking fibers and the process handling in ruby is a mess. Fiber::Scheduler is a monolithic piece, I think you'd need to add new methods here to support
wait3/wait4, then update allFiber::Schedulerimplementations. Not likely to happen without having official support forwait3/wait4in ruby.Process handling is also a mess, sometimes it registers a
SIGCHLDhandler and uses that instead ofwaitpid, and bad things can happen if youfork/waitbehindprocess.c's back. (Once I tried to write some code that calls clone on Linux. Half of the stuff you're supposed to call when forking is not exposed from libruby, and if you don't call them, you'll have random deadlocks later.)