Sounds like the plot of a Black Mirror episode :)
68 karma · joined October 8, 2022
Sounds like the plot of a Black Mirror episode :)
That sounds more like Google's captcha system. I've never seen Cloudflare Turnstile do this on any of my systems/browsers.
Remote SSH + Dev Containers and their seamless integration (even stacking one on the other) are the only features that keep me using VS Code. I would love to see the full implementation of these in an editor as fast and light weight as Zed.
From the looks of it, it seems like blocking w3schools is quite popular among Kagi users [1].
There are individuals that pay ~$4/month for GitHub Teams, plus other services (Copilot, CI, LFS, Packages, etc). They may not have public repos, but that shouldn't matter.
It also seems like the firehose of upgrades that is Sid/Experimental has slowed down a bit. Even Sid is still on nodejs 18 and not 20 or 21. The same version as both Testing and Stable.
I feel at home at home with Debian Testing, not as bleeding edge as Arch for sure, but I think that is more of a blessing than a curse. The Debian maintainers seem to know what they are doing and the distribution has a sense or maturity that some others lack. I just hope an update won't break GRUB on me :)
Only downsides to running Debian Testing is that it doesn't get security updates with the same speed as Sid or Stable, and third parties don't exactly put together and distribute pre-built packages for Testing specifically. I understand why, but it makes me wonder if things will break due some ABI compatibility issue down the line. Maybe once Debian 13 is released I'll just stick to stable.
Modern upscaling solutions (eg TAA) require not just the pixel outputs but various inter-frame/metadata such as depth, normals, motion vectors, last frame, etc. DLSS is more or less just the spiritual successor to TAA with machine learning sprinkled in. Integration with the game engine is needed because the non-color metadata needs to be provided to the DLSS and how each engine computes those things is a bit different.
I sincerely hope that LLMs won’t play a role in search, I don’t need a search engine trying to infer what I “meant” to type, Google and DDG started doing that and pushed me to Kagi as a result. Just take the words I type verbatim and search them in your index, don’t assume this is my first time using the internet.
At the end of the day none of this is any different from shipping containers or flatpaks, which bundle all the dependencies with them. In many ways Windows has escaped the DLL hell that plagued it in the past, whereas Linux still has some learning to do.
- You can't control every call to open, and thus enforce O_CLOEXEC on all files (by default)
- Because of this, most files will be leaked into the child, this is likely not desirable, especially since some distros have low open file limits for processes
- posix_spawn (the replacement for fork/exec) allows you to specify a list of file actions to perform, including opening and closing, this seems like a solution at first glance
- However, there is a TOCTOU race here, as you need to first make a list of file actions with posix_spawn_file_actions and then call posix_spawn. Note that every file you want to close needs to have it's own file action, this means you need to determine all the files that are open and manually add each one. This alone introduces the problem of determining all open files in your process.
- In a multi-threaded program it is possible for another thread to open a file between the calls to posix_spawn_file_actions and before posix_spawn, thus creating the potential for files to leak into the child.
- Even in a single threaded program, it is possible for posix_spawn to to invoke functions established with pthread_atfork, and atfork handlers are allowed to call signal-safe functions, including but not limited to open. Implementations aren't required to call atfork handlers, and modern glibc doesn't, but this is by far no guarantee.
- Therefore, my argument is that posix_spawn cannot be used to create a process with a guaranteed minimal and clean state, and so you are back to square-one with fork/exec.
The defaults for working with these APIs are just completely wrong, and very hard to get correct. The issues with fork/exec are numerous and nuanced, and most people simply aren't aware of the issues or don't care. There is a specific song and dance that needs to be performed when using fork/exec and usually you want to hide all of that behind a library function... which will look something similar to CreateProcess.... sure you might use the builder pattern to make it look nicer, but you really don't want the fork/exec split.
Here are few other issues with fork/exec, non-exhaustive:
- Only signal-safe functions can be invoked between fork and exec. This means you need to be super careful with any stdlib code you invoke between these two (or better yet, just don't).
- Multithreaded programs cannot call fork without exec. period. The state of objects such as mutexes and condition variables will be inconsistent. This is implied by the above, but I wanted to specifically call this out.
- Detecting if exec failed instead of the program requires using an extra pipe marked with CLOEXEC, I have seen too much code using a magic exit code (which is wrong)
- Cleaning up the state of the child process and not accidentally creating a zombie is a bit tricky and there are some race conditions to be aware of. pidfd is not a solution if you need to support older kernels, although helps tremendously.
- Interaction with signals is a bit messy.
- When fork is called, all pages will be marked as copy-on-write, this can be slow for processes with lots of memory allocated, and is completely redundant if your goal is to call exec. If other threads exist and are writing to memory, the pages they touch will be copied unnecessarily.
- Like I harped on earlier, files are inherited by default, not the other way around. You should be required to manually list the fds that you want the child to inherit (likely stdin, stderr and stdout only for 99% of cases).
- Distinguishing exec failure from exceeding but the process failing requires a CLOEXEC pipe
- If exec fails, _exit must be called! you cannot terminate the child in any way that might run destructors, of invoke callbacks/handlers as these can perform I/O and would thus be observable.
CreateProcess is just much better, and the whole "it takes 12 parameters how awful" argument against it is 100% a non-issue. It isn't 1960 anymore, it's okay to have a function with a name longer than 6 letters and more than 3 parameters.
The way both APIs handle file inheritance is absolutely horrendous, especially since most libcs don’t set the necessary flags. posix_spawn doesn't solve this either, since posix_atfork can open more files in the child, and multithreaded programs can have a TOCTOU bug if another thread opens files between the call to posix_spawn_file_actions and posix_spawn. TBF Windows is actually worse in this regard, since it’s race condition is a little more subtle. Ironically the best to way manage all of this nonsense is to create a child process first thing in main (another binary), which isn’t multithreaded, closes almost all files (uses a whitelist of fds) upfront, and spawns processes on behalf of the parent when requested (IPC). Ideally you would write this in C, minimize usage of libc, and avoid allocating tons of memory.