4 ms·
Your idea isn't wrong/bad... But you are aware it creates a potential race condition, right? The `stat` check and the `rm` are two separate operations, with a n
by SkittyDog 5y ago
Your idea isn't wrong/bad... But you are aware it creates a potential race condition, right? The `stat` check and the `rm` are two separate operations, with a nonzero time interval between them. So it's entirely possible for another process to delete or rename that file, after the `stat` but before the `rm` can run.
Resolving the race robustly is actually kind of hard, in Bash... You can check whether `rm` returns a nonzero exit status, but that might fail for all sorts of other reasons (e.g., bad permissions). I guess you could case/select the exit status numerically, but that could turn into a real case of bedbugs, really quick.
I guess you could repeat the `stat` check afterwards, if the ~`rm` fails? In that case, if the path doesn't exist afterwards, you can just swallow the `rm` error and let it roll.
Practically speaking, I try to avoid using Bash for anything where automatic, reliable error handling is that important... I love cool Bash tricks, but it's just not designed for sophisticated control flow.
- deleted 5y ago[deleted]
- IgorPartola 5y agoAs far as I am aware on Linux there is no way to stat and unlink in one syscall. And a second stat will create a second race condition. If you don’t want the file to exist why are you questioning whether you have permission or not? Just unlink the file via rm, if possible.
- SkittyDog 5y agoI believe you are correct about the lack of an atomic stat/unlink operation. Depending on how you implement the two steps, your potential errors are different. `rm -f` handles some errors in a different way than the stat/rm approach. One can fail where the other would not. Any given unhandled error may or may not be a problem, depending on the nature of the error, how the rest of the script is structured, and what your requirements are. There's nothing wrong with the stat/rm approach--it may be the better way to go.
- tzs 5y ago> As far as I am aware on Linux there is no way to stat and unlink in one syscall. That just means you have to do a little more work. 1. Become root. 2. Fork until the process table is full. 3. Kill all other processes. After each kill, fork until the process table is again full. 4. When all processes other than the init process are yours, you can do the stat and unlink without worrying about race conditions since there is no one else to have a race with. (Assuming the file you want to stat and unlink isn't some file that your init process is interested in, and assuming it isn't on a network drive). The side effects of this are annoying to deal with though and are probably worse than whatever problems an unhandled race condition would cause. Another approach would be to create a new user, chown the directory containing the file to that user, become that user, chmod the directory to 0300, kill any process that has that file open, do your stat and unlink, chown and chmod the directory back to what they were, and delete the earlier created user.
- julian_sark 5y agoThat's trying WAY too hard. I just reboot in single user mode. (Or, if anyone wants to get pedantic and yes, this is ruining the punchline, but alas: shutdown -h now ; then reboot from the USB stick and mount the partition ; rm file.txt).
- MichaelMoser123 5y agoI doubt that a bash script will be concurrent. If you are running your scripts in paralell, then chances are, that they will be screwed because of some other dependency/side effect.
- gpderetta 5y agoHum parallelism is pervasive in shell scripting.
- kazinator 5y ago> But you are aware it creates a potential race condition, right? If your script has to be idempotent in the face of concurrent executions of itself, then that's an extra requirement which you have to handle with locking or whatever. It is not implied by idempotency; there is meaningful idempotency which excludes the concurrency requirement. If something can rename example.txt in parallel with your script, at any time during its execution, there is nothing you can do to ensure that it's gone. Whatever step you take to ensure that its is gone can be preceded by the parallel rename.
- SkittyDog 5y agoI'm not addressing idempotency, that's a separate issue. The comparison we're discussing here is about the relative merits of `rm -f` versus the stat/rm (no '-f' option) approach. The parent post addressed a potential weakness of using the '-f' option--and the proposed alternative brings tradeoffs. I believe your point about idempotency is correct, though.