On Thu, Jul 11, 2019 at 9:27 AM Nitish Saboo <nitish.sabo...@gmail.com> wrote: > > Following is my C Code: > > 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; > } > > This is just the C wrapper that internally call syslog-ng methods. > > Since I am using an array of patterndbs, I am calling the C code with > multiple Go routines. > > Single iteration of the code is working fine. > > The issue is seen only with multiple go routines. Can we store the address of > the C struct (when memory is allocated using calloc) on Go side in an array > so that I can deallocate the memory using 'defer > C.free(unsafe.Pointer(InitStruct))' when the callback is done?This should > make multiple go routines to work...Am I right ?
I don't know what this code does, but the line pattern_db_set_emit_func(patterndb[workerId], pdbtool_pdb_emit_accumulate, cb); suggests that cb is being saved away for future use. If that is indeed the case then freeing the memory in Go will cause a dangling pointer, leading to crashes as you see. You should also double-check that each separate goroutine is using a different "workerId", as duplication of workerId values could certainly cause trouble when running concurrently. Yes, it's fine to store the address of the C struct on the Go side, if that helps. Ian > On Thu, Jul 11, 2019 at 9:39 PM Ian Lance Taylor <i...@golang.org> wrote: >> >> On Thu, Jul 11, 2019 at 7:16 AM Nitish Saboo <nitish.sabo...@gmail.com> >> wrote: >> > >> > I have the following function 'LoadPatternDB' where I am allocating memory >> > for a C struct.My C struct contains the callback function. >> > >> > 1)I cannot deference the struct in the same func 'LoadPatternDB' because I >> > get the following error when my callback function is called from C code: >> > >> > signal SIGSEGV: segmentation violation code=0x1 addr=0x7f1e00415341 >> > pc=0x7f1e00415341] >> > >> > 2)The same code is running in multiple go routines.And because of that if >> > I don't deallocate the memory I get the following error: >> > >> > *** Error in `fatal error: bin/main': double free or corruption >> > (fasttop)unexpected signal during runtime execution: 0x00007fd2b8588060 *** >> > >> > My question is: >> > >> > How can I store the address of the C struct (when memory is allocated >> > using calloc) on Go side in an array so that I can deallocate the memory >> > using 'defer C.free(unsafe.Pointer(InitStruct))' when the callback is done. >> > >> > >> > 'InitStruct := (*C.Accumulatedparams)(C.calloc(1, >> > C.sizeof_struct_Accumulatedparams))' >>>> I want to store this address on >> > Go side. >> > >> > >> > Can some please guide me here ? >> > >> > >> > 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)) >> > //defer C.free(unsafe.Pointer(InitStruct)) . <<<<<<<<<<<<<<<<<<<<<<I >> > cannot do this here >> > 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 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); >> > >> > #endif >> >> >> I don't see anything obviously wrong in your Go code, but it's >> impossible to answer your question without knowing what the C code >> does. What you describe is consistent with C code that expects to >> retain the memory passed to load_pattern_db, or alternatively is also >> consistent with C code that does not expect to be called concurrently >> from multiple threads of execution. >> >> 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/CAOyqgcU4jBvOMHqTZ%3DhyePT23Tb3DEhHhaydu6%2Bn51GW2J3Bbw%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.