I have a ruby script that forks some of the code to run it in the background and exit the command line.
The code:
fork do
#Example background code
x = 0
while x < 100 do
File.write("./example_file.txt", x.to_s, Mode: "a")
end
end
I would like to have that same script run on windows systems without the need for extra gems/libraries. I have looked at spawn() but couldn't get it to work for my needs.
fork
and Windows don't really go well together. The philosophy towards processes in Unix and Windows is very different.
In Unix, processes are the primary mechanism for functional decomposition. I.e. in Unix, an application or a service would be composed as a pipeline of multiple cooperating processes. Processes are used in Unix in a similar way as objects are in Ruby. In order for that to work, processes are cheap and lightweight.
In Windows, components are the primary mechanism for functional decomposition. I.e. in Windows, an application or a service would consist of a single process, implemented using multiple components. Components are used like objects in Ruby or processes in Unix. That means processes in Windows do not need to be cheap or lightweight, and in fact, they are pretty expensive, heavy, and slow to create and destroy.
In addition to processes being used very differently and being more expensive, they are also interacted with very differently. The APIs for creating, managing, and destroying processes are very different. There is no exact equivalent to fork
in Windows, and no easy, performant way to implement it.
Unfortunately, going to TruffleRuby or JRuby also won't help: while TruffleRuby's and JRuby's Windows support traditionally tends to be even better than YARV's, this does not apply to fork
because the JVM does not allow it: forking
on the JVM creates a fork which has only the main thread in it, but none of the GC, compiler, I/O, or other helper and auxiliary threads, which leaves you with a broken JVM. It only really works if you immediately exec
a different process, thus exiting the JVM.
That being said, this particular usage of Kernel#fork
could probably be implemented on JRuby, because (if I remember correctly), you can instantiate multiple JRuby instances in the same JVM. So, for this particular usage, where you only execute some Ruby code in the background, you don't actually need to fork
, you could spin up a new JRuby instance in a different thread.
But as far as I know, that is not implemented. (Might make an interesting project for a first contribution, though!)
The closest equivalent to your code using Kernel#spawn
in Windows would probably be something like:
spawn(RbConfig.ruby, '-e' << <<~BLOCK_END)
#Example background code
x = 0
while x < 100 do
File.write("./example_file.txt", x.to_s, Mode: "a")
end
BLOCK_END
But that is not the correct way to approach your problem. You are approaching this as an X/Y problem: you have problem X. You know that the solution in Unix is Y. Now, instead of asking the question "how do I solve problem X on Windows", you are asking the question "how do I implement solution Y on Windows", without even questioning whether Y is the right solution.
So, your question should not be what is the equivalent of fork
in Windows, but rather how to design an application in Windows.