Interesting how fundamentally simple tasks like aborting a process or rebooting the machine have very nontrivial (even kludgey) implementations.
And GNU glibc's abort():
* Writing to NULL
* Writing to address 1 (unaligned write)
* Writing to text space (read-only machine code)
* Dividing by 0
* More violence than SIGABRT (SIGILL, SIGBUS)
It's a bug in the spec, if anything.
See the abort() spec http://pubs.opengroup.org/onlinepubs/009695399/functions/abo...
Vs the exit() spec
abort() is intended as a last-ditch effort. exit() is the one that attempts to flush all open buffered file descriptors, and should be used in lieu of abort except in cases where you know you're screwed, or explicitly want to throw a signal so a debugger can take a peek.
The spec says it equals NULL, which, too, is not necessarily 0x0.
I suspect that treating expressions that demonstrably lack side effects (other than the intended segfault here of course) as statements is undefined, and hence these are getting optimised out (even with -O0).
0 cast as a pointer is defined by the spec to always be the NULL pointer, which on such architectures would have a value other than 0x0 and not point anywhere addressable.
On a more prosaic note, perhaps
This is only true if the variable in question's memory is accessed by multiple threads at the same time, and there isn't any locking or synchronization method used to protect the memory.
In this case, even though it is a globally scoped variable, it's locked by the globally scoped mutex declared in the file. All increments are done in the locked sections, so there isn't any possibility of accessing the variable without having a lock.
It should be noted that there is a very minor race condition when abort() is called in two different threads sequentially, and every attempt up to line 89 doesn't work. The first call will get the lock, then go through to line 89, where it released the lock. The second thread will then get the lock, and go through the first section. When it hits the section line 89(if (been_there_done_that == 0)), that will resolve to false, because been_there_done_that is 1. It will then go on, leaving the first thread deadlocked at the LOCK attempt on line 91. This shouldn't result in any missed functionality, but I actually wonder why they're releasing the lock in the first place. Raise() isn't thread safe anyway, because the signal is applied to all threads in the process. Plus, you're trying to suicide the program. It's a bad idea to even have the possibility of multiple threads trying to kill themselves at the same time.
A few months ago I fixed this exact bug in a developer's code, on a 8-bit embedded processor.
And since abort still needs to work even without locks and on every platform...
But it contains hints of Drepperification, like the superfluous use of preincrement.
Sounds like you just have an axe to grind with Drepper.
I thoroughly enjoyed his article about memory. He is obviously an extremely intelligent and knowledgeable guy.
I am afraid that he is too clever by half though, insofar as good code is clean and readable first, and clever second. Every time I've had an opportunity to interact with the glibc codebase I'm dismayed that such an important, core piece of software has been written so cleverly that it essentially can only be maintained by one guy.
It's an issue of mixed tab-space indentation, with tabs being displayed at 4 spaces instead of the 8 spaces they were intended to be.