5 ms·
If you were wondering, this is how fork() is implemented: as threads: https://github.com/dboland/minc/blob/8fe124625d2262b5bd83e0abf96df5cab791443a/libposix/vfs
by cryptonector 1y ago
If you were wondering, this is how fork() is implemented: as threads: https://github.com/dboland/minc/blob/8fe124625d2262b5bd83e0abf96df5cab791443a/libposix/vfs/process/process_sched.c#L48 https://github.com/dboland/minc/blob/8fe124625d2262b5bd83e0a...
- thingfish 1y agoCool. You found out why MinC is not Cygwin. To fork(), Cygwin starts a second copy of the entire executable. CreateThread() is much closer to what UNIX does. Any thoughts? BTW, there's another "easteregg".
- cryptonector 1y agoNot sure I'll look for the other "easteregg", though I noticed that you set the new thread's impersonation token, which is presumably how you implement setuid() and friends [yes, that is how you implement them] -- is that the other easteregg? I also see that you use the last RID of SIDs as the UID/GID, and that you have hardcoded passwd(4)/group(4) entries, so you only support local users (which is fine). Oh, ah, _task_copy(). You swap stacks... I think because of course. Your execve() is real though, since you use CreateProcessAsUser(), which is good. The compromise you made is pretty neat, though obviously some things might not work well. Though I'm guessing this is working quite well for you. Your file names are weird; they often tell me nothing about what to expect to find in them. I looked for fork() because that's the difficult one to implement on WIN32. What Cygwin does is some crazy gymnastics that sometimes fails. You might know that I think fork() is "evil" [0], or if you hadn't, you do now, and I guess you're likely to agree with that take, but I'd love to hear your thoughts on that, because clearly you've thought about fork(). I've to say that you've clearly thought a lot about this, and though I've not tried it (and probably won't) you seem to have done an excellent job. [0] https://gist.github.com/nicowilliams/a8a07b0fc75df05f684c23c18d7db234 https://gist.github.com/nicowilliams/a8a07b0fc75df05f684c23c...
- thingfish 1y ago> I've to say that you've clearly thought a lot about this, and though I've not tried it (and probably won't) you seem to have done an excellent job. Thank you. I needed that. I started the project in 2016 and have been obsessed with it since then. The weird thing is that I never had to use workarounds or hacks that are mentioned by the Cygwin team [0]. For instance, the select() call does map cleanly on top of the Win32 API. I just needed to use WSAWaitForMultipleEvents() instead of WaitForMultipleEvents() (the other "easteregg"). Why the Cygwin people didn't figure this out baffles me. I guess their current code base doesn't allow the rewrite. My big breakthrough was when I realized that the "inconsistent interfaces" [1] in Win32 file handles can be implemented as virtual file systems. One for each handle type (char, disk, pipe, etc). That was my "throwing away 1000 lines of code" [2] moment. As to the weird file names, I use the file names OpenBSD uses. My rule is to always use the file name of the header (.h) file where the system call is declared in OpenBSD. I also use their struct and constant names, prefixed with "WIN_". The "fork is evil" thing is discussed a lot in the programmers community. I myself find it quite clever. Threads are highly volatile and are very hard to program without running into race conditions. The solution is to make a copy of everything the child will be using: duplicate file descriptors, the stack, globals (rss). The kernel does all this for you in one system call. I often wonder how the people who complain about the absence of real concurrency in their programming languages [3] actually would use this feature. In my opinion the best way to use concurrency is to string individual programs into a pipeline. This will never go "evil" on you. [0] https://cygwin.com/cygwin-ug-net/highlights.html https://cygwin.com/cygwin-ug-net/highlights.html [1] https://www.usenix.org/legacy/publications/library/proceedings/usenix-nt97/full_papers/korn/korn.pdf https://www.usenix.org/legacy/publications/library/proceedin... [2] https://skeptics.stackexchange.com/questions/43800/did-the-creator-of-unix-say-one-of-my-most-productive-days-was-throwing-away-10 https://skeptics.stackexchange.com/questions/43800/did-the-c... [3] https://news.ycombinator.com/item?id=32408577 https://news.ycombinator.com/item?id=32408577
- cryptonector 1y ago> Thank you. I needed that. I started the project in 2016 and have been obsessed with it since then. Well, like I said, I'm impressed. > I myself find [fork()] quite clever. Oh for sure it is clever. Though vfork() would have been more clever. The thing that fork() did that was very nice is make it real easy to spawn processes in a shell, which meant not having to design a spawn() system call (which are invariably large APIs), which greatly simplified Unix development in the 70s, both kerne-land and user-land. vfork() would have been more clever, but that didn't occur to Ritchie, Thompson, et. al. I wonder how things would have gone if they had thought of vfork().