mirror of
https://github.com/Motion-Project/motion.git
synced 2026-01-24 14:48:42 -05:00
count webcontrol as a thread to avoid a crash
On a SIGHUP restart the main thread waits to restart until all worker threads are finished executing, except webcontrol wasn't included. If it was still running (such as reading a web request), it would have a dangling context pointer after cnt_list was freed leading to a crash. This counts that thread in the running threads, as a termination webcontrol_finish variable to terminate it indepdent of the device thread, and creates a webcontrol_running to identify when it is running.
This commit is contained in:
@@ -143,6 +143,7 @@ Bugfixes
|
||||
* Fixed leak in vloopback.
|
||||
* Fixed a build of motion for some kernel version with not good videodev.h
|
||||
* Netcam Modulo 8
|
||||
* Fix webhttpd race condition crash with SIGHUP, add it to running thread counter (David Fries)
|
||||
|
||||
3.2.12 Summary of Changes
|
||||
|
||||
|
||||
3
CREDITS
3
CREDITS
@@ -473,6 +473,9 @@ Mark Feenstra
|
||||
Miguel Freitas
|
||||
* Came up with the round robing idea.
|
||||
|
||||
David Fries
|
||||
* Fix webhttpd race condition crash with SIGHUP, add it to running thread counter
|
||||
|
||||
Aaron Gage
|
||||
* Pointed me to the vid_mmap/int problem when calling SYNC in
|
||||
video.c
|
||||
|
||||
23
motion.c
23
motion.c
@@ -341,6 +341,7 @@ static void sig_handler(int signo)
|
||||
while (cnt_list[++i]) {
|
||||
cnt_list[i]->makemovie = 1;
|
||||
cnt_list[i]->finish = 1;
|
||||
cnt_list[i]->webcontrol_finish = 1;
|
||||
/*
|
||||
* Don't restart thread when it ends,
|
||||
* all threads restarts if global restart is set
|
||||
@@ -2723,8 +2724,21 @@ int main (int argc, char **argv)
|
||||
* Create a thread for the control interface if requested. Create it
|
||||
* detached and with 'motion_web_control' as the thread function.
|
||||
*/
|
||||
if (cnt_list[0]->conf.webcontrol_port)
|
||||
pthread_create(&thread_id, &thread_attr, &motion_web_control, cnt_list);
|
||||
if (cnt_list[0]->conf.webcontrol_port) {
|
||||
pthread_mutex_lock(&global_lock);
|
||||
threads_running++;
|
||||
/* set outside the loop to avoid thread set vs main thread check */
|
||||
cnt_list[0]->webcontrol_running = 1;
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
if (pthread_create(&thread_id, &thread_attr, &motion_web_control,
|
||||
cnt_list)) {
|
||||
/* thread create failed, undo running state */
|
||||
pthread_mutex_lock(&global_lock);
|
||||
threads_running--;
|
||||
cnt_list[0]->webcontrol_running = 0;
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
}
|
||||
}
|
||||
|
||||
MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO, "%s: Waiting for threads to finish, pid: %d",
|
||||
getpid());
|
||||
@@ -2746,6 +2760,9 @@ int main (int argc, char **argv)
|
||||
if (cnt_list[i]->running || cnt_list[i]->restart)
|
||||
motion_threads_running++;
|
||||
}
|
||||
if (cnt_list[0]->conf.webcontrol_port &&
|
||||
cnt_list[0]->webcontrol_running)
|
||||
motion_threads_running++;
|
||||
|
||||
if (((motion_threads_running == 0) && finish) ||
|
||||
((motion_threads_running == 0) && (threads_running == 0))) {
|
||||
@@ -2805,7 +2822,7 @@ int main (int argc, char **argv)
|
||||
|
||||
|
||||
// Be sure that http control exits fine
|
||||
cnt_list[0]->finish = 1;
|
||||
cnt_list[0]->webcontrol_finish = 1;
|
||||
SLEEP(1, 0);
|
||||
MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO, "%s: Motion terminating");
|
||||
|
||||
|
||||
3
motion.h
3
motion.h
@@ -370,6 +370,9 @@ struct context {
|
||||
volatile unsigned int restart; /* Restart the thread when it ends */
|
||||
/* Is the motion thread running */
|
||||
volatile unsigned int running;
|
||||
/* Is the web control thread running */
|
||||
volatile unsigned int webcontrol_running;
|
||||
volatile unsigned int webcontrol_finish; /* End the thread */
|
||||
volatile int watchdog;
|
||||
|
||||
pthread_t thread_id;
|
||||
|
||||
13
webhttpd.c
13
webhttpd.c
@@ -2515,7 +2515,7 @@ void httpd_run(struct context **cnt)
|
||||
client_socket_fd = acceptnonblocking(sd, NONBLOCK_TIMEOUT);
|
||||
|
||||
if (client_socket_fd < 0) {
|
||||
if ((!cnt[0]) || (cnt[0]->finish)) {
|
||||
if ((!cnt[0]) || (cnt[0]->webcontrol_finish)) {
|
||||
MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO, "%s: motion-httpd - Finishing");
|
||||
closehttpd = 1;
|
||||
}
|
||||
@@ -2545,6 +2545,17 @@ void *motion_web_control(void *arg)
|
||||
{
|
||||
struct context **cnt = arg;
|
||||
httpd_run(cnt);
|
||||
|
||||
/*
|
||||
* Update how many threads we have running. This is done within a
|
||||
* mutex lock to prevent multiple simultaneous updates to
|
||||
* 'threads_running'.
|
||||
*/
|
||||
pthread_mutex_lock(&global_lock);
|
||||
threads_running--;
|
||||
cnt[0]->webcontrol_running = 0;
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO, "%s: motion-httpd thread exit");
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user