On 7-Jul-2008, at 19:38 , Bill Erickson wrote:

I have not taken the time to heavily debug this yet, but I wanted to pass it on in case the solution is obvious to anyone else. The code I'm writing
parses an opensrf message, using jsonParseString under the covers, and
segfaults while trying to take advantage of the jsonObject re-use code.

---
// definition of freeObjList
union unusedObjUnion{
    union unusedObjUnion* next;
    jsonObject obj;
};
typedef union unusedObjUnion unusedObj;
static unusedObj* freeObjList = NULL;
-----

The call to freeObjList->next is what segfaults

if( freeObjList ) {
    o = (jsonObject*) freeObjList;
    freeObjList = freeObjList->next;
    unusedObjRelease++;
    currentListLen--;
} else {
    ...


Am I crazy, or should unusedObjUnion actually be implemented as a struct and
not a union, since it needs to actively maintain pointers to the next
unusedObjUnion and its jsonObject simultaneously? I.e. a union can only
store data for one field at any given time.

No, it doesn't maintain both links simultaneously. It's one or the other. freeObjList is a list of chunks of memory that are the size of a jsonObject, all linked together through pointers stored in the 'next' field (which overlaps with the obj field).

The code above saves the pointer to the head of the free list into a jsonObject pointer, then bumps the freelist pointer to the next item in the free list, which is exactly right. The code then returns 'o', which is a pointer to a jsonObject sized chunk of memory.


Another example occurs during the addition of a new jsonObject to the
freeObjeList:

unusedObj* unused = (unusedObj*) o; // o is a jsonObject*
unused->next = freeObjList;

At this point, "unused" no longer contains a valid reference to the jsonObject
since it is clobbered by the call to unused->next = freeObjList.

Thanks in advance for any schooling or insight.

This is also right, although it's incomplete. The next line of code better be

        freeObjList = unused;

Otherwise, you just keep dropping pointers.


-------------------
GDB Output for the segfault I'm seeing:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb77a7700 (LWP 20128)]
jsonNewObject (data=0x0) at osrf_json_object.c:86
warning: Source file is more recent than executable.
86                      freeObjList = freeObjList->next;
(gdb) bt
#0  jsonNewObject (data=0x0) at osrf_json_object.c:86
#1  0xb733eace in jsonNewObjectType (type=1) at osrf_json_object.c:170
#2  0xb73416f9 in jsonObjectDecodeClass (obj=0x8220848) at
osrf_json_tools.c:113
#3  0xb7341254 in jsonParseString (
str=0x82e7738 "[{\"__p\": {\"threadTrace\": 1, \"locale\": \"en_US\", \"type\": \"REQUEST\", \"payload\": {\"__p\": {\"params\": [\"Hello, World!
\"], \"method\nsrf.system.echo\"}, \"__c\": \"osrfMethod\"}}, \"__c\":
\"osrfMessage\"}]") at osrf_json_parser.c:596
#4  0xb7476c13 in osrf_message_deserialize (
string=0x82e7738 "[{\"__p\": {\"threadTrace\": 1, \"locale\": \"en_US\", \"type\": \"REQUEST\", \"payload\": {\"__p\": {\"params\": [\"Hello, World!
\"], \"methopensrf.system.echo\"}, \"__c\": \"osrfMethod\"}}, \"__c\":
\"osrfMessage\"}]", msgs=0xbfe47bac, count=256) at osrf_message.c:253
#5  0xb775fdcb in osrfHttpTranslatorParseRequest (trans=0x82e7260) at
osrf_http_translator.c:204
#6  0xb776046d in osrfHttpTranslatorProcess (trans=0x82e7260) at
osrf_http_translator.c:316
#7  0xb77609a0 in handler (r=0x82f0c88) at osrf_http_translator.c:430
#8  0x080794a9 in ap_run_handler ()
#9  0x0807c8b7 in ap_invoke_handler ()
#10 0x08089f00 in ap_process_request ()
#11 0x0808720b in ?? ()
#12 0x08080aa9 in ap_run_process_connection ()
#13 0x0808e339 in ?? ()
#14 0x0808e677 in ?? ()
#15 0x0808f067 in ap_mpm_run ()
#16 0x08066dd5 in main ()
(gdb)

-b

--
Bill Erickson
| VP, Software Development & Integration
| Equinox Software, Inc. / The Evergreen Experts
| phone: 877-OPEN-ILS (673-6457)
| email: [EMAIL PROTECTED]
| web: http://esilibrary.com

--
David J. Fiander
Library Software Development


Reply via email to