memcached/memcached — pull request #67 by zwChan (2014-04-23 10:35:13+00:00)
Title: solution for Issue 260:

----------------------------
I get the same problem as issue 260, and the SA reset the
memcache process and can't not reproduce it. But after
analyse the issue260 and the code for several days, i think
there is something we should do.
first, as the error info:
0). "Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb655ab40 (LWP 9131)]
do_slabs_alloc (id=1, size=size@entry=76) at slabs.c:241
241	p->slots = it->next;"
Found:
1). it is Page fault error;
2). the errorno "6" means: no page found && read access
&& user-mode access;
(Ref: linux core code: arch/*/mm/fault.c)
/*
27 * Page fault error code bits:
28 *
29 * bit 0 == 0: no page found 1: protection fault
30 * bit 1 == 0: read access 1: write access
31 * bit 2 == 0: kernel-mode access 1: user-mode access
32 * bit 3 == 1: use of reserved bit detected
33 * bit 4 == 1: fault was an instruction fetch
34 */

3). from 0) 1) 2), it turn out that the code "slabs.c:241 p->slots = it->next;"
try to read a null pointer(it, aka p->slots).
4). before using poiter "p->slots" @<2><3> as following code,
check its counter "p->sl_curr" @<1> instead of checking the pointer.
it suppose 'when the counter is no-zero, the pointer is not null.'
is this true in
every extreamly case? i am sorry i can not find it out, it looks like
it is locked every time before updating the p-losts and p->sl_curr.
and again, it suppose the "the lock working perfectly"; i don't want trouble
myself, it shoul check the pionter before using it, nor check other-related
resource.

slabs.c:233
/* fail unless we have space at the end of a recently allocated page,
we have something on our freelist, or we could allocate a new page */
if (! (p->sl_curr != 0 || do_slabs_newslab(id) != 0)) {
/* We don't have more memory available */
ret = NULL;
} else if (p->sl_curr != 0 && p->slots) { /////-------><1>
/* return off our freelist */
it = (item *)p->slots; /////-------><2>
p->slots = it->next; /////-------><3>
if (it->next) it->next->prev = 0;
p->sl_curr--;
ret = (void *)it;
}

modified: slabs.c