Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I fork a go process?

Tags:

fork

go

exec

I want to fork a go process and get back the id of the new process(es), but all I can see in the exec or os libraries is to start a new process.

like image 340
Shashwat Avatar asked Feb 06 '15 16:02

Shashwat


1 Answers

You supposedly want syscall.ForkExec() from the syscall package.

Note that fork() has been invented at the time when no threads were used at all, and a process had always had just a single thread of execution in it, and hence forking it was safe. With Go, the situation is radically different as it heavily uses OS-level threads to power its goroutine scheduling.

Now, unadorned fork(2) on Linux will make the child process have just the single thread—the one which called fork(2) in the parent process—among all those which were active, including some crucial threads used by the Go runtime. Basically this means that you simply cannot expect the child process to be able to continue executing Go code, and the only thing you can sensibly do is to somehow immediately perform exec(2). Notice that that's what syscall.ForkExec() is supposed to be used for.

And now think about the problem further. I'd say these days the only thing a direct call to fork(2) is useful for is "best-effort asynchronous process state snapshotting"—the kind, say, Redis uses. This technique relies on the fact the child process inherits all the memory data pages from its parent, but the OS uses copy-on-write technique to not really copy all that data, so the child can just sit there and save all the data structures to disk while its parent is chugging away modifying them in its own address space. Every other conceivable use for fork() implies immediate exec(), and that's what exec.Command() et al is for, so why just not use it?

like image 171
kostix Avatar answered Sep 21 '22 17:09

kostix