data-loop: add option to pthread_cancel the thread

Don't use pthread_cancel by default to stop the data thread but
instead use an eventfd. pthread_cancel uses a signal and is not
nice to use in a library as it can cause strange crashes.

See #211
This commit is contained in:
Wim Taymans 2020-03-02 15:44:47 +01:00
parent ce80e05b25
commit e76351da79
2 changed files with 31 additions and 2 deletions

View file

@ -86,9 +86,17 @@ static void *do_loop(void *user_data)
return NULL; return NULL;
} }
static void do_stop(void *data, uint64_t count)
{
struct pw_data_loop *this = data;
pw_log_debug(NAME" %p: stopping", this);
this->running = false;
}
static struct pw_data_loop *loop_new(struct pw_loop *loop, const struct spa_dict *props) static struct pw_data_loop *loop_new(struct pw_loop *loop, const struct spa_dict *props)
{ {
struct pw_data_loop *this; struct pw_data_loop *this;
const char *str;
int res; int res;
this = calloc(1, sizeof(struct pw_data_loop)); this = calloc(1, sizeof(struct pw_data_loop));
@ -110,10 +118,23 @@ static struct pw_data_loop *loop_new(struct pw_loop *loop, const struct spa_dict
} }
this->loop = loop; this->loop = loop;
if (props == NULL ||
(str = spa_dict_lookup(props, "loop.cancel")) == NULL ||
pw_properties_parse_bool(str) == false) {
this->event = pw_loop_add_event(this->loop, do_stop, this);
if (this->event == NULL) {
res = -errno;
pw_log_error(NAME" %p: can't add event: %m", this);
goto error_loop_destroy;
}
}
spa_hook_list_init(&this->listener_list); spa_hook_list_init(&this->listener_list);
return this; return this;
error_loop_destroy:
if (this->created && this->loop)
pw_loop_destroy(this->loop);
error_free: error_free:
free(this); free(this);
error_cleanup: error_cleanup:
@ -146,6 +167,8 @@ void pw_data_loop_destroy(struct pw_data_loop *loop)
pw_data_loop_stop(loop); pw_data_loop_stop(loop);
if (loop->event)
pw_loop_destroy_source(loop->loop, loop->event);
if (loop->created) if (loop->created)
pw_loop_destroy(loop->loop); pw_loop_destroy(loop->loop);
free(loop); free(loop);
@ -203,8 +226,13 @@ int pw_data_loop_stop(struct pw_data_loop *loop)
{ {
pw_log_debug(NAME": %p stopping", loop); pw_log_debug(NAME": %p stopping", loop);
if (loop->running) { if (loop->running) {
pw_log_debug(NAME": %p cancel", loop); if (loop->event) {
pthread_cancel(loop->thread); pw_log_debug(NAME": %p signal", loop);
pw_loop_signal_event(loop->loop, loop->event);
} else {
pw_log_debug(NAME": %p cancel", loop);
pthread_cancel(loop->thread);
}
pw_log_debug(NAME": %p join", loop); pw_log_debug(NAME": %p join", loop);
pthread_join(loop->thread, NULL); pthread_join(loop->thread, NULL);
pw_log_debug(NAME": %p joined", loop); pw_log_debug(NAME": %p joined", loop);

View file

@ -316,6 +316,7 @@ struct pw_data_loop {
struct pw_loop *loop; struct pw_loop *loop;
struct spa_hook_list listener_list; struct spa_hook_list listener_list;
struct spa_source *event;
pthread_t thread; pthread_t thread;
unsigned int created:1; unsigned int created:1;