Hi Ian,

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 ?
Thanks,
Nitish

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/CALjMrq77%3D_zZefBkJL1vBFSRvg2hwWfg6G3pHeOMH5EGWJBznQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to