File descriptor ownership and lifetimes Lassi Kortela 09 May 2019 12:00 UTC
From the first draft: > Ports are garbage-collected Scheme objects, not integers. When a port is garbage collected, it is also closed. Because file descriptors are just integers, it's impossible to garbage collect them — you wouldn't be able to close file descriptor 3 unless there were no 3's in the system. > Suppose we have a Scheme port constructed on top of file descriptor 3. We intend to fork off a program that will inherit this file descriptor. If we drop references to the port, the garbage collector may prematurely close file 3 before we fork the subprocess. > Unfortunately, there is no even vaguely portable solution to this problem. Scsh and Guile undertake heroic measures to open new file descriptors for ports when the old file descriptors are repurposed for something else, and to track when closing a port implies closing its file descriptor or not. But doing so involves more changes than an implementation should have to make in order to provide this SRFI. Remarks: - In one way, it's even more difficult than this. Several file descriptors (even in different processes!) can refer to the same "ofile" (a file handle in the kernel). This notoriously affects things like the flag that sets whether reads are blocking or non-blocking. - It would appear to me that the concept of a Scheme port that does _not_ close the underlying file descriptor when it's GC'd is absolutely necessary for a sane OS API. - I would leave it up to users to ensure that they use the right mix of fd-closing and non-fd-closing ports for their application. It seems almost impossible to anticipate all use cases if the Scheme implementation tries to keep tally of all open ports to particular fd's. Even if it's possible, it's probably complex and extremely subtle so it would the abstraction would leak. But I haven't thought in detail about this problem. It would be good to hear more from the people who implemented this stuff in Scsh and Guile. - I would just live with the fact that Scheme ports and fd's are two different "namespaces" (or object spaces) that do not inform each other when one of them changes. I would leave it all up to the application programmer (who will be the one writing the code to make the relevant changes anyway).