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:
David Fries
2012-11-08 23:14:29 -06:00
parent 0629d9db61
commit bab15abfee
5 changed files with 39 additions and 4 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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");

View File

@@ -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;

View File

@@ -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);
}