Reputation: 243
I'm having an interesting problem, which I hope is entirely my fault.
I have code which is reading from a queue, as in:
do {
evt = &newevts[ evt_head++ ];
evt_head &= MAX_EVENTS;
if (evt->index <= 0 || evt->index > MAX_INDEX) {
printf("RX EVENT BAD NDX: ndx=%d h=%d\n",evt->index, evt_head);
continue;
}
//... etc ...
} while(evt_head != evt_tail) ;
The bizarre issue is the if statement can evaluate to evt->index being a bad value, but when the printf displays it shows a perfectly valid value! Example:
RX EVENT BAD NDX: ndx=1 h=64
The if statement clearly shows the condition must be <= 0 OR > 1024 (max index). To make matters worse, this only occurs once in a while. I'm using GCC, Centos 6.3. No threads touch evt_head except this thread. (I've renamed it a few times and re-compiled just to be sure.)
The tail is handled by a function which adds items to the queue in the same manner the head removes them (increment then AND). I have also added a counter inside the event structure itself to record the head/tail values as events are placed into the queue and find no lost or skipped values. It literally looks as though I'm getting some bad memory reads. But that's ridiculous - I'd expect system crashes or at least program crashes if that was the case.
Any ideas on how in the world this could be happening sporadically? (Frequency is about 1 out of 100 reads) I appreciate any input!
typedef struct {
int index;
int event;
} EVENT;
#define MAX_EVENTS 0x01ff
#define MAX_INDEX 1024
No threads or other code touches evt_head. Only this loop. The queue is never anywhere near full. I also happen to have a "SPIN LOCK" on entry to the routine which adds to the queue (in preparation for it being other-thread-accessed later), and an UNLOCK on exit.
Upvotes: 4
Views: 140
Reputation: 5664
My guess is that the function adding events to your tail will change evt_tail
before writing the index
field. This allows your reader to access an event that is still in the process of being written.
Upvotes: 2