Background jobs with #fork
normalperson at yhbt.net
Thu Apr 12 23:04:57 UTC 2012
Patrik Wenger <paddor at gmail.com> wrote:
> Thanks for the answers.
> Isn't there another way to retrieve the right socket?
Actually, I think my proposed patch (in reply to Hongli) at
should fix your issue.
> > I can probably writeup a better explanation (perhaps on the usp.ruby
> > (Unix Systems Programming for Ruby mailing list) if this doesn't make
> > sense.
> Yeah I don't really understand this part. The "hanging" Unicorn worker
> can read another request because the client socket wasn't closed
> because it's still open in the child process? I would appreciate a
> better explanation, thank you.
Basically, fork() has a similar effect as dup() in that it creates
multiple references to the same kernel object (the client socket).
close() basically lowers the refcount of a kernel object, when the
refcount is zero, resources inside the kernel are freed. When
the refcount of a kernel object reaches zero, a shutdown(SHUT_RDWR)
This works for 99% of Rack apps since they don't fork() nor call dup()
on the client socket, so refcount==1 when unicorn calls close(), leading
to unicorn setting refcount=0 upon close() => everything is freed.
However, since the client socket increments refcount via fork(),
close() in the parent (unicorn worker) no longer implies
parent timeline | child timeline
accept() -> sockfd created | (child doesn't exist, yet)
sockfd.refcount == 1 |
fork() | child exists, now
sockfd is shared by both processes now: sockfd.refcount == 2
if either the child or parent forks again: sockfd.recount += 1
close() => sockfd.recount -= 1 | child continues running
since sockfd.refcount == 1 at this point, the socket is still
considerd "alive" by the kernel. If the child calls close()
(or exits), sockfd.refcount is decremented again (and now
Now, to write this as a commit message :>
More information about the mongrel-unicorn