multithreading - Stopping pthread as soon as struct is freed in C -
i have worker thread processing queue of work items. implemented second worker process items inserted in worker1
. however, came across invalid reads
while using valgrind.
i'm assuming because struct foo
pass worker2()
freed @ point in main thread. struct foo
struct gets updated (malloc/free), however, i'd worker2
insert missing items foo
.
my question is: possible worker2
stop processing struct foo
null
? , start again when create_foo()
called? i'm not sure best approach insert missing items foo
thread? feedback appreciated.
//canonical form //producer void push_into_queue(char *item) { pthread_mutex_lock(&queuemutex); if (workqueue.full) { // full } else { add_item_into_queue(item); pthread_cond_signal(&queuesignalpush); } pthread_mutex_unlock(&queuemutex); } } // consumer1 void *worker1(void *arg) { while (true) { pthread_mutex_lock(&queuemutex); while (workqueue.empty) pthread_cond_wait(&queuesignalpush, &queuemutex); item = workqueue.front; // pop queue add_item_into_list(item); pthread_cond_broadcast(&queuesignalpop); pthread_mutex_unlock(&queuemutex); } return null; } pthread_create(&thread1, null, (void *) &worker, null); // consumer2 void *worker2(void *arg) { my_struct *foo = (my_struct *) arg; while (true) { pthread_mutex_lock(&queuemutex); while (list.empty) pthread_cond_wait(&queuesignalpop, &queuemutex); (i = 0; < list.size; i++) insert_item_into_foo(list[i].item, foo); pthread_cond_broadcast(&queuesignalpop); pthread_mutex_unlock(&queuemutex); } return null; } void create_foo() { my_struct *foo = calloc(10, sizeof(my_struct)); pthread_create(&thread2, null, (void *) &worker2, foo); } void free_foo() { pthread_mutex_lock(&queuemutex); int i; (i=0; i<5; i++) free(foo[i].list->string); free(foo[i].list); free(foo); pthread_mutex_unlock(&queuemutex); }
you did not define terminating condition both worker1
, worker2
. suppose eol of foo
considered such. means both workers must monitor existence of foo
owning reference (ie. foo **
).
void *worker2(void *arg) { my_struct **foo = (my_struct **) arg; while(true) { pthread_mutex_lock(&queuemutex); while (list.empty) pthread_cond_wait(&queuesignalpop, &queuemutex); if (null == *foo) break; (i = 0; < list.size; i++) insert_item_into_foo(list[i].item, *foo); pthread_cond_broadcast(&queuesignalpop); pthread_mutex_unlock(&queuemutex); } free(foo); return null; } void create_foo() { my_struct *foo = calloc(10, sizeof(my_struct )); my_struct **foo_ptr = malloc(1, sizeof(my_struct *)); *foo_ptr = foo; pthread_create(&thread2, null, (void *) &worker2, foo_ptr); // more work foo }
note somehow foo
must assigned different variable reachable in free_foo
(your code supposes fact without explicitely showing - hence comment @ end of create_foo
).
with code above, each instance of worker2
owns pointer rely on whole lifetime, , must take care of before exiting.
update:
perhaps better solution consists in passing struct thread2
, contains foo
pointer, flag indicating if pointer still valid. may add other piece of information needed thread in struct ad lib.
struct th2_data { enum {running, terminating} state; my_struct *foo; };
then allocate instance of struct, initialize {running, foo}
, , pass thread2
. keep copy of address somewhere able signal terminating
state thread2
. indeed, asked in comments, have replace if (null == *foo)
test in thread2 if (foo.state == terminating)
.
Comments
Post a Comment