nullplan wrote:
rdos wrote:
I don't find fork() that horrible, but it should be implemented late in the OS and after there is a CreateProcess-like interface. It's a fun challenge to get fork() right, and I don't think every odd feature of it must be supported.
A while ago, someone proposed a different abstraction here: An egg. Basically, a process in creation. So, in addition to the POSIX process states of "alive" and "zombie", there is also the "egg". The idea being that you create a new OS object, that you can then change with different APIs, to finally spawn the process at the end (shouldn't that be "hatch" then?) This way, you again have the arbitrary number of steps between child process creation and the start of the next process that made the fork()/exec() model such a success, and the whole thing is extensible.
First, I don't create a single forked tree like POSIX OSes do. Rather, the use of fork() and exec() are inside ported applications, and typically will be done in a process that was initially created with CreateProcess(). I also use it in the command shell to spawn a process inside the same console as CreateProcess() will create a new console too. Also, when exec() is called, all the history of the fork is deleted and the resulting child is redone to a process that is indistinguishable from a process created with CreateProcess().
nullplan wrote:
If you later think of a new thing you need to pass on to a child process, you can add a new API. See, this is my major problem with CreateProcess(): You want to change anything about the child process the system call designer did not consider, you are SOL. There is no way to change the environment variables just for the child, for instance. No way to pass file descriptors other than the standard three. No way to set the user for the child. Etc.
I pass command-line, startup directory and environment to the child, but if file descriptor sharing is desired, then fork() / exec() must be used.'
nullplan wrote:
And what, precisely, is the benefit of that? Why do you think that file type abstraction is a hack? Well, OK, it is, but only because the abstraction is leaky (there are some things you can only do with some file descriptors). The basic idea, that read() and write() do sensible things, whether the plugged-in file is a disk file, a pipe, or a terminal, is still sound. This means, for instance, you can write a utility that expects a stream of text on standard input and writes it back out to standard output, but with line numbers in front. And you can call that utility with stdin being a disk file or a pipe or a socket, or maybe even a device file, and stdout being something completely different, and the utility doesn't have to care.
As an example, read() from a socket cannot handle timeouts on the socket, and so might hang-up if the socket is terminated without being closed properly (which seems to be the default today). write() on a socket could block because the output buffer is full, and then hangup indefinitely too. The same applies to pipes.
nullplan wrote:
In your regiment, this is impossible in general, and cumbersome in the special case that you enumerate all resource types.
It still can be done, but requires explicit mapping of a resource to a C handle (provided it is sane & supported). IOW, you cannot open a resource as a C handle by opening a device in the filesystem, or using any other strange filename. You always must open it using the native API.
nullplan wrote:
CGI started out with this idea, that you just redirect the output of a script to a socket. And indeed, writing TCP services such that they read from stdin and write to stdout makes them way easier to test. Then you only need a general purpose TCP server that spawns your client handler as needed and boom, you're done. Also, I just invented inetd.
Sure, and it will malfunction when something unexpected happens to the socket. In addition to that, sockets must have timeouts that are checked regularly, wasting CPU time for no reason. My native socket API has a push() method to force the data to be sent immediately without a timeout.