How to avoid a set of values /collected in .so callback calls/ frompointing to same address?

J

jollyroger

Hi all.
It seems that here's a problem with a pointer constantly bound to some
fixed address.

// compile with: g++ 1.cc -o test -Wall `pkg-config --cflags --libs
glib-2.0` -lgthread-2.0
// or g++ 1.cc -o testq -lglib-2.0 -I/usr/include/glib-2.0 -I/usr/
lib64/glib-2.0/include/ -lgthread-2.0c


#include <glib.h>
#include <iostream>
#include <string.h>
int counter;
GAsyncQueue *q;

typedef struct MyStruct {
int foo;
char *data;
} *MyStructPtr;

gpointer looper(gpointer data) {
g_thread_init(NULL);
while (1) {
while (g_async_queue_length(q) > 0) {
MyStructPtr xtransport;
xtransport = new struct MyStruct;
xtransport = (MyStructPtr)g_async_queue_try_pop(q);

// The actual code is acting as weird, as if we have here, xtransport-
data = last_text_value_ever_received;
std::cout said:
data << ":str\n";
}
}
}
void adder(char *data) {
char *processedData;
// someExternalAPICallToprocessData(data, &processeddata);
processedData = (char *)data;
MyStructPtr dtransport;
dtransport = new struct MyStruct;

dtransport->data = processedData;//processeddata;
dtransport->foo = ++counter;

g_async_queue_push(q, (gpointer*) dtransport);
}
int main() {
GThread *l;
g_thread_init(NULL);
q = g_async_queue_new();
l = g_thread_create(looper, NULL, FALSE, NULL);
sleep(2);
char *t;
t = strdupa("1111");
adder(t);
t = strdupa("222");
adder(t);
sleep (5);
}

This is a working lab mockup of some larger project. On the project, a
strange behavior is noticed;

instead of main(), we're sitting in a callback function, that gets
some data from a system component. Trying to print (e.g. cout) that
data before putting to queues, can get something like:
N1 (in Callback): aaaabbbbcccc
N2 (in Callback): bbbbaaaacccc.

Same, if the access to (newly set pointer ) dtransport->data is made
in a same code where it was created (mainloop/callback function)t;
that's fine.

But can't get the correct value of the first elements in the queue!
Data fields is always the same - accessing the collected data via
queue, can get only the value that was set in last callback; evil
pointer hell supposed!
str #1: bbbbaaaacccc.
str #2: bbbbaaaacccc.

The question is, **would that
someExternalAPICallTOprocessData() fill &processeddata with a pointer
to a fixed address storing only the data of last call**?
How to get a copy of char* being returned and safely put it into
MyStruct ?Note, that a next function uses offsets...

process(dequeued->data);
void process(char *data) {
my *ptr = NULL;
ptr = data + SOME_SIZE_CONST
...
}

And somehow, memcpy'ng the content of processedData seems to segfault
the .so library which contains someExternalAPICallTOprocessData(). In
the mockup context, it is the end of adder(); in the real context it
is end of callback function to kernel networking stuff; so funny.

gcc 4.4.5.

cheers,
 
A

AnonMail2005

Hi all.
It seems that here's a problem with a pointer constantly bound to some
fixed address.

// compile with: g++ 1.cc -o test  -Wall `pkg-config --cflags --libs
glib-2.0` -lgthread-2.0
// or g++ 1.cc -o testq -lglib-2.0 -I/usr/include/glib-2.0 -I/usr/
lib64/glib-2.0/include/ -lgthread-2.0c

#include <glib.h>
#include <iostream>
#include <string.h>
int counter;
GAsyncQueue *q;

typedef struct MyStruct {
int foo;
char *data;

} *MyStructPtr;

gpointer looper(gpointer data) {
                g_thread_init(NULL);
                while (1) {
                                while (g_async_queue_length(q) > 0) {
                                                MyStructPtr xtransport;
                                                xtransport = new struct MyStruct;
                                                xtransport = (MyStructPtr)g_async_queue_try_pop(q);

 // The actual code is acting as weird, as if we have here, xtransport->data = last_text_value_ever_received;

                                                std::cout << "str # " << xtransport->foo << ":" << xtransport->data << ":str\n";

                                }
                }}

void adder(char *data) {
                char *processedData;
                // someExternalAPICallToprocessData(data, &processeddata);
                processedData = (char *)data;
                MyStructPtr dtransport;
                dtransport = new struct MyStruct;

                dtransport->data = processedData;//processeddata;
                dtransport->foo = ++counter;

                g_async_queue_push(q, (gpointer*) dtransport);}

int main() {
                GThread *l;
                g_thread_init(NULL);
                q = g_async_queue_new();
                l = g_thread_create(looper, NULL, FALSE, NULL);
                sleep(2);
                char *t;
                t = strdupa("1111");
                adder(t);
                t = strdupa("222");
                adder(t);
                sleep (5);

}

This is a working lab mockup of some larger project. On the project, a
strange behavior is noticed;

instead of main(), we're sitting in a callback function, that gets
some data from a system component. Trying to print (e.g. cout) that
data before putting to queues, can get something like:


Same, if the access to (newly set pointer ) dtransport->data is made
in a same code where it was created (mainloop/callback function)t;
that's fine.

But can't get the correct value of the first elements in the queue!
Data fields is always the same - accessing the collected data via
queue, can get only the value that was set in last callback; evil
pointer hell supposed!


The question is, **would that
 someExternalAPICallTOprocessData() fill &processeddata with a pointer
to a fixed address storing only the data of last call**?
How to get a copy of char* being returned and safely put it into
MyStruct ?Note, that a next function uses offsets...

    process(dequeued->data);
    void process(char *data) {
     my *ptr = NULL;
     ptr = data + SOME_SIZE_CONST
    ...
    }

And somehow, memcpy'ng the content of processedData seems to segfault
the .so library which contains someExternalAPICallTOprocessData(). In
the mockup context, it is the end of adder(); in the real context it
is end of callback function to kernel networking stuff; so funny.

gcc 4.4.5.

cheers,

You neeed to make a copy of the char * data passed into your
callback. Once the callback function ends, the data is probably freed
by the function that called your callback.

Figure out how many bytes are in the data and make a copy of it so you
can store it in your struct. It's not clear from your code what the
lenght of the data is.

HTH
 
V

Venu Yanamandra

Hi all.
It seems that here's a problem with a pointer constantly bound to some
fixed address.

// compile with: g++ 1.cc -o test  -Wall `pkg-config --cflags --libs
glib-2.0` -lgthread-2.0
// or g++ 1.cc -o testq -lglib-2.0 -I/usr/include/glib-2.0 -I/usr/
lib64/glib-2.0/include/ -lgthread-2.0c

#include <glib.h>
#include <iostream>
#include <string.h>
int counter;
GAsyncQueue *q;

typedef struct MyStruct {
int foo;
char *data;

} *MyStructPtr;

gpointer looper(gpointer data) {
                g_thread_init(NULL);
                while (1) {
                                while (g_async_queue_length(q) > 0) {
                                                MyStructPtr xtransport;
                                                xtransport = new struct MyStruct;
                                                xtransport = (MyStructPtr)g_async_queue_try_pop(q);

 // The actual code is acting as weird, as if we have here, xtransport->data = last_text_value_ever_received;

                                                std::cout << "str # " << xtransport->foo << ":" << xtransport->data << ":str\n";

                                }
                }}

void adder(char *data) {
                char *processedData;
                // someExternalAPICallToprocessData(data, &processeddata);
                processedData = (char *)data;
                MyStructPtr dtransport;
                dtransport = new struct MyStruct;

                dtransport->data = processedData;//processeddata;
                dtransport->foo = ++counter;

                g_async_queue_push(q, (gpointer*) dtransport);}

int main() {
                GThread *l;
                g_thread_init(NULL);
                q = g_async_queue_new();
                l = g_thread_create(looper, NULL, FALSE, NULL);
                sleep(2);
                char *t;
                t = strdupa("1111");
                adder(t);
                t = strdupa("222");
                adder(t);
                sleep (5);

}

This is a working lab mockup of some larger project. On the project, a
strange behavior is noticed;

instead of main(), we're sitting in a callback function, that gets
some data from a system component. Trying to print (e.g. cout) that
data before putting to queues, can get something like:


Same, if the access to (newly set pointer ) dtransport->data is made
in a same code where it was created (mainloop/callback function)t;
that's fine.

But can't get the correct value of the first elements in the queue!
Data fields is always the same - accessing the collected data via
queue, can get only the value that was set in last callback; evil
pointer hell supposed!


The question is, **would that
 someExternalAPICallTOprocessData() fill &processeddata with a pointer
to a fixed address storing only the data of last call**?
How to get a copy of char* being returned and safely put it into
MyStruct ?Note, that a next function uses offsets...

    process(dequeued->data);
    void process(char *data) {
     my *ptr = NULL;
     ptr = data + SOME_SIZE_CONST
    ...
    }

And somehow, memcpy'ng the content of processedData seems to segfault
the .so library which contains someExternalAPICallTOprocessData(). In
the mockup context, it is the end of adder(); in the real context it
is end of callback function to kernel networking stuff; so funny.

gcc 4.4.5.

cheers,


Hi jollyroger,
Why dont you use strdup instead of strdupa. Free "t" as soon as adder
returns and call strdup again for the next call.

From the man pages, strdupa uses "alloca" and this is found a little
buggy.

--
The alloca() function is machine and compiler dependent. On
many systems its implementation is buggy. Its use is discouraged.

On many systems alloca() cannot be used inside the list of
arguments of a function call, because the stack space reserved by
alloca()
would appear on the stack in the middle of the space for the
function arguments.

--

Lets see if it gets the desired output!

Regards,
Venu Yanamandra
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top