From: Richard M K. <kr...@pr...> - 2007-12-20 20:21:07
|
"Far=C3=A9" writes: > I'd rather we have two layers, one that is a thin wrapper over POSIX > and returns integers and for which you have to waitpid and/or use > custom sigchld handlers (with proper API), and one on top than returns > process objects.=20 Note that my compromise proposal does return pids as the first value from SB-POSIX:FORK, so existing programs should continue to work unchanged. What I am proposing is that FORK implicitly create and intern PROCESS instances, and that the WAIT family implicitly do bookkeeping on those processes. This bookkeeping I'm proposing will be invisible to you if you don't hold onto the second return value from SB-POSIX:FORK, even, I think, if you install your own SIGCHLD handler that uses the wait() family of functions in SB-POSIX, because the bindings to the wait() functions will use the machinery like what we already have for cleaning up PROCESS instances. I have not yet tried implementing the proposal to see how well it works, so there might be something I'm not thinking of. But I don't think that having SB-POSIX:FORK and SB-POSIX:WAIT* share bookkeeping machinery with RUN-PROGRAM should adversely affect any uses of FORK or WAIT. > The first layer may allow to write semi-portable programs that do the > right thing. Note that such programs won't port to Windows, for example, where we don't have SB-POSIX:FORK. I don't know whether other Lisps expose so primitive a fork() binding as we do; if they do, they may have similar flaws in this area. So if your definition of "portable" is "runs on SBCL where SBCL runs well", I might call the definition laudable, but perhaps unusual ;) > You'll need that internally, anyway -- I think it would be a good > policy to export it. I don't agree with the general "operation O requires primitives P1 and P2, therefore there should be a supported interface to the raw P1 and P2 operations" is faulty. For example, IIRC, we don't have a supported interface for circumventing the handler that invokes the garbage collector. In the case of fork(), we do export the "raw" primitive, and I am arguing that it is destabilizing in an analogous way. If we changed things so that our FORK and WAIT did a bit of bookkeeping behind the scenes, but you wanted to circumvent our attempts to keep things consistent, it would be trivial to get your own destabilizing fork(): (define-alien-routine "fork" sb-alien:int) But I'd hope that users would look for FORK in SB-POSIX first, and prefer the FORK we offer there, which we can at least try to implement in a manner that doesn't break other parts of the system. > NB: I'm writing a library that uses fork for robust(er) multitasking. Okay. Does your library set a SIGCHLD handler? Were you aware that that every call to RUN-PROGRAM (including, for instance, invocations of the C compiler in ASDF systems) will replace your handler, and that installation of your handler will break RUN-PROGRAM's process management, with the consequence that some ways that you might handle SIGCHLD can prevent processes created by RUN-PROGRAM from ever being wait()ed for? You might be aware of these details; but maybe you weren't. ISTM that we'd be making your library more reliable by giving you an SB-POSIX that ensured that all of SBCL's children were taken care of, if we can do so. -- RmK |