I've mentioned this elsewhere in the thread, but I think it's a difference of view on what malloc represents. Operating systems do have "reserve this part of the address space" APIs and these reservations don't get charged against your commit because you're simply reserving the space, not committing to using it, and so the operating system doesn't need to back it with anything.
In this worldview, malloc is like me buying a plane ticket at the counter for a specific flight that's going to leave soon. I'd be really annoyed if I were bumped off a flight I just paid for (and would've rather been told "that flight is full, try again later" (malloc returns NULL)). This is, for example what Windows does. Under memory pressure, it'll say to applications, "hey no I'm not in a giving mood for memory right now" (and will sometimes bump the size of the pagefile if configured to do this, but only up to a point).
The thought behind this is that well... applications have to handle malloc returning NULL anyway. Whether that's calling abort and giving up is one matter, another might be to retry the allocation at a later time (maybe after Windows has bumped the pagefile size), another might be to handle an error using some preallocated buffer or whatever.
To be 100% fair, it's rare that processes are cloned on Windows, if only because it's part of the Native API that applications generally don't use directly, and CreateProcess is easier and does all the housekeeping stuff, etc, that people writing Windows applications generally come to expect (or don't even know happens)
I do think overcommit was a poor design choice, but I think it probably mostly does logically follow from the fact that fork and friends are the only ways available to create a process that's available to userspace. It's quite unfortunate though.
Part of the problem is that some applications wanted to reserve lots of address space but didn't necessarily want to touch it right away (such as when they were using it sparsely). Something that VirtualAlloc(x, MEM_RESERVE) (or mmap(..., MAP_NORESERVE)) would be suited for. But while malloc exists, mreserve doesn't in libc, and I think it was pretty uncommon to use it.
Windows doesn't use fork/exec for process creation in any relevant way today
There are Native APIs for implementing fork (needed for the obsolete POSIX subsystem, primarily), but even on the Native API side, processes are usually spawned through NtCreateProcess or RtlCreateUserProcess, though there is a bunch of setup with regards to the Csr APIs for the Win32 CreateProcess[1]).
It has also created this unfortunate assumption a lot of the time that malloc and friends are (infallible OR crash) and, separately, can sometimes have potentially weird tendencies to force undefined behaviors on otherwise well-defined programs (I think primarily around mmap, although I'm not remembering the details super well).
Agreed though, overcommit is the culprit here. I get why it happened (unfortunate consequences of fork and friends existing as the way to spawn tasks and wanting those to be both performant and not fail in frustrating conditions), but I don't think it was a design that aged particularly well.
I actually like somewhat the notion of how Windows handles these two things
1. For address space reservations, you can reserve address space but in order to touch it you have to commit it. Commits have to be backed by something (RAM, a file, pagefiles if they exist) and if a commit fails, they'll get NULL back from malloc. It allows code to be more correct in the face of low-memory conditions or to try again later (Firefox for example, does this[1] on Windows).
2. Process creation is done with a specific API to create processes. The only problem with this I think is that you have to specify everything at creation time, but you could augment this by creating processes in a stopped state (iirc Linux has to do this anyway to set up some stuff before it can hand over control back to userland) and having the parent send FDs to the child or whatnot. Windows... doesn't do this, it has a couple of kitchen sink APIs for creating processes and setting up stuff like the standard streams... in any case I'm getting off topic.
Don't think there's much about that design that can be changed now though
> These days you can do oom score adjusting, which is not as strong as a pardon.
Writing -1000 to /proc/<pid>/oom_score_adj will cause the OOM killer not to consider the process at all :)
From the man page proc_pid_oom_score_adj(5)
> The value of oom_score_adj is added to the badness score before it is used to determine which task to kill. Acceptable values range from -1000 (OOM_SCORE_ADJ_MIN) to +1000 (OOM_SCORE_ADJ_MAX). [...]. The lowest possible value, -1000, is equivalent to disabling OOM-killing entirely for that task, since it will always report a badness score of 0.
I'm not sure if it was what OP meant, but it's arguably a good availability technique (as long as you can generate the checksum, that is). Like, if I want to run custom firmware and flash it, having a checksum which verifies that the firmware isn't corrupted may help prevent bricking.
"Unable to reproduce" is a fair enough explicit close reason. This is more about those "stale" bots that exist that just kinda close the issues because there hasn't been any response for X days. The annoyance with the practice usually stems from the fact that many of the victims of this comes from a lack of maintainer response.
This sort of bot punishes users for making even valid reports that aren't fixed immediately or missed by the maintainers for whatever reason including transitory ones, etc.
Constantly bumping threads/issues/whatever is generally considered rude, so this is why issue reporters generally don't do it, plus generally the reporter isn't solely focused on that particular issue
Aside from the fact that you can do this statelessly (you could stuff a JWT or moral equivalent in the header as a Bearer token), if you were okay with server-side state, you can have the token be related to a principal or have permissions in of itself.
reply