On 7/31/06, Christian christian@pflanze.mine.nu wrote:
At 1:04 Uhr +0800 31.07.2006, TJay wrote:
I wasn't thinking about file descriptors in particular. I was wondering whether gambit itself has any internal state that's not friendly with fork(). (I have no idea what these states might include.)
I think I've already given my non-authoritative answer (just a guess): if you have multiple gambit threads running, then call fork, both processes will continue running all the threads, and if you print some stuff to buffered ports but do not flush nor close (through the POSIX call) them, you'll get output being printed twice. I don't know how I would handle the former problem (I think there's no place where Gambit is doing this already; the only place where Gambit calls fork is in implements ___device_stream_setup_from_process in os_io.c and there is no need to shut down other threads as exec is called immediately).
I see. I've not thought of how threads would be affected, and I'd hate to think of the kinds of strange, hidden bugs I'd get from unflushed buffered ports. I'll have to be super careful if I do any forking.
BTW using fork as opposed to starting subprocesses using open-process will probably not give you much of an advantage, if you load all code as compiled shared libraries, since almost all shareable memory will then be shared anyway, and you don't seem to want to fork chilren at a high frequency.
You're right. It might be easier to just call open-process. Thanks for the heads up.
tj
Afficher les réponses par date
FWIW, I've now extended/written (well, it previously only had getpid) a POSIX interface. It only contains a handful of functions currently, but it's a start, and I think I've got the basics, especially the error handling, done quite well.
I've put it up at http://scheme.mine.nu/gambit/scratch/cj-posix/ . As always, it's written for my chjmodule system, but it shouldn't be difficult to get to work independantly.
Some usage examples:
(bruse cj-posix) (_close 132)
#<posix-exception #2 errno: 9>
(posix-exception? #2)
#t
(posix-exception-message #2)
"Bad file descriptor"
(posix-exception-errno #2)
9
(close 132)
*** ERROR IN (stdin)@4.1 -- close (fd): (132) "Bad file descriptor" 1>
For all POSIX functions which can return errors, I'm exporting two functions, following this principle: the function with an underscore prepended does not throw exceptions; in case of an error, it returns a posix-exception structure. This is efficient, and Schemier (and safer against usage errors) than handling untyped integer values, and it solves the problem that the separate errno variable cannot be safely read from scheme (as the runtime may wipe it out before the user gets a chance to see the value). The function without the underscore throws a (currently untyped) exception on errors.
Some more examples:
(pipe)
#s32(3 4)
(define in (fd->port 3 'RDONLY)) (define out (fd->port 4 'WRONLY)) out
#<output-port #3 (fd-4)>
(display "Hallo\n" out) (force-output out) (read in)
Hallo
(define ex (let ((pid (fork))) (println "pid: " pid) (if (> pid 0) (let ((s (s32vector 1))) (waitpid pid s 0) s) "in child")))
pid: 0
pid: 27649
ex "in child"
(_exit 12) ex
#s32(3072)
(WIFEXITED ex)
#t
(WEXITSTATUS ex)
12
(WTERMSIG ex)
*** ERROR IN (console)@7.1 -- status value is not suited for this operation: #s32(3072) WTERMSIG 1>
At 9:28 Uhr +0800 31.07.2006, TJay wrote:
I see. I've not thought of how threads would be affected, and I'd hate to think of the kinds of strange, hidden bugs I'd get from unflushed buffered ports. I'll have to be super careful if I do any forking.
I think (with some awareness of the issues) it may not be that difficult.
Me too, I'll need multiprocessig soon, for web services. I may try both approaches (or maybe first forking). At least I (or we) now have the choice.
Christian.