Hi, I have the following function 'LoadPatternDB' where I am allocating memory for a C struct.My C struct contains the callback function. I have the function 'LoadPatternDB' that is running in multiple go routines.I have written a C wrapper that internally uses syslog-ng methods. While running the method 'LoadPatternDB' in syslogparser.go with multiple go routines, I get the following error.
**** Error in `fatal error: bin/main': double free or corruption (fasttop)unexpected signal during runtime execution: 0x00007fd2b8588060 **** My queries are: 1)When do we get this error ? 2)Is it because of not deallocating the struct memory, I am getting this error ?But at the same time I am allocating separate memories for each of the go routines. 3)Is it because of the memory crunch on the system that can lead to this error ? 4)The issues is seen with only multiple go routines.Single iteration of the code is working fine. 5)Can I not call Go code and C code using multiple threads ? Can some one please guide me here ? syslog-node.c =========== PatternDB *patterndb[WORKERIDS]; int load_pattern_db(const gchar* filename, key_value_cb cb, int workerId) { if(patterndb[workerId] != NULL){ pattern_db_free(patterndb[workerId]); } patterndb[workerId] = pattern_db_new(); pattern_db_reload_ruleset(patterndb[workerId], configuration, filename); pattern_db_set_emit_func(patterndb[workerId], pdbtool_pdb_emit_accumulate, cb); return 0; } gboolean pdbtool_accumulate_fields(NVHandle handle, const gchar *name, const gchar *value, gssize length, gpointer user_data) { struct Accumulatedparams *params = user_data; key_value_cb cb = params->callback; cb(name, value, length, params->data); return FALSE; } void pdbtool_pdb_emit_accumulate(LogMessage *msg, gboolean synthetic, gpointer user_data) { nv_table_foreach(msg->payload, logmsg_registry, pdbtool_accumulate_fields, user_data); } syslogparser.go ============= func (obj SyslogParser) LoadPatternDB(opts Syslog, workerId int) { patterndbpath := C.CString(opts.Patterndb) defer C.free(unsafe.Pointer(patterndbpath)) InitStruct := (*C.Accumulatedparams)(C.calloc(1, C.sizeof_struct_Accumulatedparams)) InitStruct.callback = (C.key_value_cb)(C.callback) InitStruct.data = C.int(workerId) C.load_pattern_db(patterndbpath, (*C.Accumulatedparams)(unsafe.Pointer(InitStruct)), C.int(workerId)) } //export Result func Result(key *C.char, value *C.char, value_len C.size_t, mapid C.int) { fmt.Println("Map Id: " + strconv.Itoa(int(mapid))) value_field := C.GoStringN(value, C.int(value_len)) key_field := C.GoString(key) remap, ok := constants.FIELD_MAPPINGS[key_field] if ok { Check.result[int(mapid)][remap] = value_field //check.result[remap] = value_field } else { //check.result[key_field] = value_field Check.result[int(mapid)][key_field] = value_field } } cfuncs.go -======== package lib /* #include <stdio.h> // The gateway function void callback(char *key, char *value, size_t value_len, int mapid) { //printf("C.callOnMeGo_cgo(): called"); void Result(const char *key, const char *value, size_t value_len, int mapid); Result(key, value, value_len, mapid); } */ import "C" syslog-node.h ============ #ifndef TEST_H_INCLUDED #define TEST_H_INCLUDED #include <stdlib.h> typedef void (*key_value_cb)(const char* key, const char* value, size_t value_len, int data); typedef struct Accumulatedparams{ key_value_cb callback; int data; }Accumulatedparams; int load_pattern_db(const char* filename, Accumulatedparams *cb, int workerId); #endif On Fri, Jul 12, 2019 at 12:32 AM Nitish Saboo <nitish.sabo...@gmail.com> wrote: > This is the code snippet I was talking about: > > store := make([]*C.struct_Accumulatedparams, 2) > > > func (obj Syslogparser) LoadPatternDB(opts Syslog) { > > > > patterndb_path := C.CString(opts.patterndb) > > store[0] = (*C.Accumulatedparams)(C.calloc(1, > C.sizeof_struct_Accumulatedparams)) > > store[0].callback = (C.key_value_cb)(C.callOnMeGo_cgo) > > store[0].data = C.int(1) > > C.load_pattern_db(patterndb_path, > (*C.Accumulatedparams)(unsafe.Pointer(store[0]))) > > } > > > On Fri, 12 Jul 2019, 00:22 Nitish Saboo, <nitish.sabo...@gmail.com> wrote: > >> Hi Ian, >> >> Can you please guide me with the correct way to store the address of a C >> struct in a Go array so that I can use it later for deallocating the memory? >> >> Thanks, >> Nitish >> >> On Fri, 12 Jul 2019, 00:04 Ian Lance Taylor, <i...@golang.org> wrote: >> >>> On Thu, Jul 11, 2019 at 10:58 AM Nitish Saboo <nitish.sabo...@gmail.com> >>> wrote: >>> > >>> > pattern_db_set_emit_func(patterndb[workerId], >>> pdbtool_pdb_emit_accumulate, cb); >>> > suggests that cb is being saved away for future use. >>> > >>> > >>>>yes cb is being saved away and is being used for future use for >>> callbacks to Go code. >>> >>> Then clearly the Go code must not immediately free the C memory. That >>> is no different from how C code would work. >>> >>> >>> > syslog-node.h >>> > ============ >>> > >>> > #ifndef TEST_H_INCLUDED >>> > #define TEST_H_INCLUDED >>> > >>> > #include <stdlib.h> >>> > typedef void (*key_value_cb)(const char* key, const char* value, >>> size_t value_len, int data); >>> > typedef struct Accumulatedparams{ >>> > key_value_cb callback; >>> > int data; >>> > }Accumulatedparams; >>> > int initialize_engine(const char* filename, const char* module_path); >>> > int reload_pattern_db(const char* filename, Accumulatedparams *cb, >>> int workerId); >>> > int load_pattern_db(const char* filename, Accumulatedparams *cb, int >>> workerId); >>> > >>> > >>>>>If I declare the array in the following manner: >>> > >>> > result := make([]*C.struct_Accumulatedparams) >>> > store[0] = (*C.Accumulatedparams)(C.calloc(1, >>> C.sizeof_struct_Accumulatedparams)) >>> > >>> > Here also the code gets compiled successfully, just that the GoLand >>> IDE shows store[0].callback and store[0].data in red color saying >>> Unresolved reference 'callback' and Unresolved reference 'data' >>> respectively.Not sure how the code compiles if the IDE shows it in red >>> color. Binary(./main) works fine >>> >>> I don't know what the GoLand IDE does. I don't see any >>> store[0].callback or store[0].data in that code snippet. >>> >>> >>> > Though this works, >>> > >>> > store[0] = (*C.Accumulatedparams)(C.calloc(1, >>> C.sizeof_struct_Accumulatedparams)) >>> > InitStruct := store[0] >>> > InitStruct.callback = (C.key_value_cb)(C.callOnMeGo_cgo) >>> > InitStruct.data = C.int(1) >>> > >>> > Here the code compiles successfully and there is no complain from >>> GoLand IDE as well.Binary (./main) too works fine >>> > >>> > So what i thought to do : >>> > >>> > type Store struct{ >>> > result []*C.struct_Accumulatedparams >>> > data []C.int >>> > callback []C.key_value_cb >>> > } >>> > >>> > var store = Store{result: make([]*C.struct_Accumulatedparams, 2), >>> data: make([]C.int ,2), callback:make([]C.key_value_cb, 2)} >>> > >>> > func (obj Syslogparser) LoadPatternDB(opts Syslog) { >>> > >>> > patterndb_path := C.CString(opts.patterndb) >>> > store.result[0] = (*C.Accumulatedparams)(C.calloc(1, >>> C.sizeof_struct_Accumulatedparams)) <<<<<< >>> > store.callback[0] = (C.key_value_cb)(C.callOnMeGo_cgo) <<<<< >>> > store.data[0] = C.int(1) >>> > C.load_pattern_db(patterndb_path, >>> (*C.Accumulatedparams)(unsafe.Pointer(store.result[0]))) >>> > } >>> > >>> > Here the code gets compiled successfully. But I am getting the >>> following error when I run the binary './main' >>> > >>> > 1In reload PatternDb: >>> > PatternDb :/home/nsaboo/Documents/goworkspace/src/poc/reload.xml >>> > ModulePath :usr/local/lib/syslog-ng >>> > fatal error: unexpected signal during runtime execution >>> > [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x0] >>> > >>> > runtime stack: >>> > runtime.throw(0x4fa203, 0x2a) >>> > /usr/local/go/src/runtime/panic.go:617 +0x72 >>> > runtime.sigpanic() >>> > /usr/local/go/src/runtime/signal_unix.go:374 +0x4a9 >>> > >>> > goroutine 1 [syscall]: >>> > runtime.cgocall(0x4b8fb0, 0xc000042cc8, 0x4d9280) >>> > /usr/local/go/src/runtime/cgocall.go:128 +0x5b fp=0xc000042c98 >>> sp=0xc000042c60 pc=0x404f6b >>> > main._Cfunc_execute_percustomer_db(0x7fb0fb5a5fa0, 0x1d5, >>> 0x7fb0fb8259b0, 0x8) >>> > _cgo_gotypes.go:121 +0x45 fp=0xc000042cc8 sp=0xc000042c98 pc=0x4b5ca5 >>> > main.Syslogparser.ParseMessagePerCustomer(0xc0000a2000, 0x36, >>> 0x4f6b0c, 0x18, 0x4f3fc4, 0x8, 0xc0000d0000, 0x1d5) >>> > /home/nsaboo/Documents/goworkspace/src/poc/main.go:132 +0x109 >>> fp=0xc000042d38 sp=0xc000042cc8 pc=0x4b6f09 >>> > main.perCustomerParsing(...) >>> > /home/nsaboo/Documents/goworkspace/src/poc/main.go:249 >>> > main.main() >>> > /home/nsaboo/Documents/goworkspace/src/poc/main.go:232 +0x6e1 >>> fp=0xc000042f98 sp=0xc000042d38 pc=0x4b78e1 >>> > runtime.main() >>> > /usr/local/go/src/runtime/proc.go:200 +0x20c fp=0xc000042fe0 >>> sp=0xc000042f98 pc=0x42cd9c >>> > runtime.goexit() >>> > /usr/local/go/src/runtime/asm_amd64.s:1337 +0x1 fp=0xc000042fe8 >>> sp=0xc000042fe0 pc=0x4548c1 >>> > } >>> > >>> > >>> > Where am i going wrong here ? >>> >>> Somewhere your C code is getting a NULL pointer dereference. >>> >>> I don't see much in these questions that seems specific to Go. >>> >>> Ian >>> >> -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CALjMrq4GDLv1CZVUL47U1tN0Qn%3DAjYEdq%3D-naQGT%3DZ_jMi0wpQ%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.