What is the equivalent of Ruby Process.detach?

Thanks.

1 Like

Process.run waits for process to complete. And if you want to achieve asynchronous execution, you can spawn that in fiber.

 spawn { Proces.run (........) }

But keep in mind, Crystal is Single Threaded by default (unless you are in preview mode), so all things will run in same thread.

HIH

Hi, i am migrate a ruby gem into crystal, a gem like Foreman but things are designed to run in both foreground/background, here is the Process related code.

It’s seem like same code can be write use Crystal like this:

x = Process.new(command: "sleep 10000", shell: true)
puts x.pid

Process.new will return a Process object immediately, this behavior seem like same as ruby Process.spawn, as describe as following:

This method is similar to Kernel#system but it doesn't wait for the command to finish.

The parent process should use Process.wait to collect the termination status of its child or use Process.detach to register disinterest in their status; otherwise, the operating system may accumulate zombie processes.

But, there is no equivalent of Process.detach(pid) in Crystal, will it cause zombie processes if we don’t use it at some case?

i still don’t know spawn { Process.run(...) } or Process.new which one should be used for this case too.

Question would be, do you need to interact with process after you run that from your Crystal code? if yes then go with Process.new and keep hold of Process object, invoke Process#wait in a separate fiber. This use case is useful if you are interacting with a process via pipes and need to do some kind of communication and at end of your program closure, you need to terminate that.

And if your code doesn’t need any other interaction with process object and all you need is just start a process then you can invoke Process.run in a separate fiber.

Something like

 proc = Process.new(command: "sleep 10000", shell: true)
 spawn { proc.wait}
# continue with your work
# pass around proc object to some code which need to do some further handling
# invoking either close or terminate on proc object at end of your interaction or program closure

OR

spawn { Process.run(command: "sleep 10000", shell: true) }
# continue with your work

HIH

1 Like

Thanks, the case is first one.

proc = Process.new(command: "sleep 10000", shell: true)
 spawn { proc.wait}

One more question to clarify, after the first line run, we got the Process object proc(we can get pid from this object too), so, the spawn { proc.wait }, do the same thing as Ruby Process.detach, right?

As the Process.detach definition in Ruby doc.


Process#wait will wait for the process to finish. But keep in mind that Crystal by default is single threaded and if your main thread terminates before process is finished, then fiber will terminate and you will have zombie process. If you need to ensure that process is terminated before your application closes, either use some channels to let main thread wait till fiber(s) are finished or send close/terminate or kill signal to processes object to ensure that get terminated.

2 Likes