diff --git a/src/htsp_server.c b/src/htsp_server.c index 8c1f2271..990194f6 100644 --- a/src/htsp_server.c +++ b/src/htsp_server.c @@ -2065,6 +2065,8 @@ htsp_serve(int fd, void **opaque, struct sockaddr_storage *source, htsp_connection_t htsp; char buf[50]; htsp_subscription_t *s; + + // Note: global_lock held on entry tcp_get_ip_str((struct sockaddr*)source, buf, 50); @@ -2084,7 +2086,6 @@ htsp_serve(int fd, void **opaque, struct sockaddr_storage *source, htsp.htsp_peer = source; htsp.htsp_writer_run = 1; - pthread_mutex_lock(&global_lock); LIST_INSERT_HEAD(&htsp_connections, &htsp, htsp_link); pthread_mutex_unlock(&global_lock); @@ -2105,8 +2106,6 @@ htsp_serve(int fd, void **opaque, struct sockaddr_storage *source, pthread_mutex_lock(&global_lock); - *opaque = NULL; - /* Beware! Closing subscriptions will invoke a lot of callbacks down in the streaming code. So we do this as early as possible to avoid any weird lockups */ @@ -2128,11 +2127,6 @@ htsp_serve(int fd, void **opaque, struct sockaddr_storage *source, pthread_join(htsp.htsp_writer_thread, NULL); - free(htsp.htsp_logname); - free(htsp.htsp_peername); - free(htsp.htsp_username); - free(htsp.htsp_clientname); - htsp_msg_q_t *hmq; TAILQ_FOREACH(hmq, &htsp.htsp_active_output_queues, hmq_link) { @@ -2148,6 +2142,14 @@ htsp_serve(int fd, void **opaque, struct sockaddr_storage *source, htsp_file_destroy(hf); close(fd); + + /* Free memory (leave lock in place, for parent method) */ + pthread_mutex_lock(&global_lock); + free(htsp.htsp_logname); + free(htsp.htsp_peername); + free(htsp.htsp_username); + free(htsp.htsp_clientname); + *opaque = NULL; } /* diff --git a/src/http.c b/src/http.c index d5717f88..a01bde42 100644 --- a/src/http.c +++ b/src/http.c @@ -790,6 +790,8 @@ http_serve(int fd, void **opaque, struct sockaddr_storage *peer, htsbuf_queue_t spill; http_connection_t hc; + // Note: global_lock held on entry */ + pthread_mutex_unlock(&global_lock); memset(&hc, 0, sizeof(http_connection_t)); *opaque = &hc; @@ -804,10 +806,6 @@ http_serve(int fd, void **opaque, struct sockaddr_storage *peer, http_serve_requests(&hc, &spill); - free(hc.hc_post_data); - free(hc.hc_username); - free(hc.hc_password); - http_arg_flush(&hc.hc_args); http_arg_flush(&hc.hc_req_args); @@ -815,9 +813,12 @@ http_serve(int fd, void **opaque, struct sockaddr_storage *peer, htsbuf_queue_flush(&spill); close(fd); + // Note: leave global_lock held for parent pthread_mutex_lock(&global_lock); + free(hc.hc_post_data); + free(hc.hc_username); + free(hc.hc_password); *opaque = NULL; - pthread_mutex_unlock(&global_lock); } #if 0 diff --git a/src/tcp.c b/src/tcp.c index d258e572..20a204a4 100644 --- a/src/tcp.c +++ b/src/tcp.c @@ -439,16 +439,16 @@ tcp_server_start(void *aux) notify_reload("connections"); pthread_mutex_unlock(&global_lock); } + pthread_mutex_lock(&global_lock); tsl->ops.start(tsl->fd, &tsl->opaque, &tsl->peer, &tsl->self); /* Stop */ if (tsl->ops.stop) tsl->ops.stop(tsl->opaque); if (tsl->ops.status) { - pthread_mutex_lock(&global_lock); LIST_REMOVE(tsl, link); notify_reload("connections"); - pthread_mutex_unlock(&global_lock); } + pthread_mutex_unlock(&global_lock); free(tsl); return NULL;