diff --git a/src/alg_sec.cpp b/src/alg_sec.cpp index 6c1d92cf..23351f8c 100644 --- a/src/alg_sec.cpp +++ b/src/alg_sec.cpp @@ -568,6 +568,7 @@ void algsec_deinit(ctx_cam *cam) pthread_mutex_destroy(&cam->algsec->mutex); delete cam->algsec; + cam->algsec = NULL; #else (void)cam; diff --git a/src/dbse.cpp b/src/dbse.cpp index 4faa952b..e657ad59 100644 --- a/src/dbse.cpp +++ b/src/dbse.cpp @@ -162,7 +162,9 @@ void dbse_global_init(struct ctx_motapp *motapp) indx = 0; while (motapp->cam_list[indx] != NULL) { - motapp->cam_list[indx]->dbse = (struct ctx_dbse *)mymalloc(sizeof(struct ctx_dbse)); + if (motapp->cam_list[indx]->conf->database_type != "") { + motapp->cam_list[indx]->dbse = new ctx_dbse; + } indx++; } @@ -418,7 +420,8 @@ void dbse_deinit(struct ctx_cam *cam) #ifdef HAVE_SQLITE3 /* Close the SQLite database */ - if (cam->conf->database_type == "sqlite3") { + if ((cam->conf->database_type == "sqlite3") && + (cam->dbse->database_sqlite3 != NULL)) { sqlite3_close(cam->dbse->database_sqlite3); cam->dbse->database_sqlite3 = NULL; } @@ -1059,6 +1062,7 @@ void dbse_motpls_deinit(struct ctx_cam *cam) dbse_motpls_free_movies(cam); dbse_motpls_free_cols(cam); delete cam->dbsemp; + cam->dbsemp = NULL; } } diff --git a/src/motion_loop.cpp b/src/motion_loop.cpp index 6c16b6c8..f2d6b8e7 100644 --- a/src/motion_loop.cpp +++ b/src/motion_loop.cpp @@ -736,36 +736,15 @@ static int mlp_init(struct ctx_cam *cam) /** clean up all memory etc. from motion init */ void mlp_cleanup(struct ctx_cam *cam) { - /* When the watchdog counter is less than zero we - * only do the minimal necessary to free the memory variables - * rather than finish off any event processing - */ - if (cam->watchdog > 0) { - event(cam, EVENT_TLAPSE_END, NULL, NULL, NULL, NULL); - if (cam->event_nr == cam->prev_event) { - mlp_ring_process(cam); - if (cam->imgs.image_preview.diffs) { - event(cam, EVENT_IMAGE_PREVIEW, NULL, NULL, NULL, &cam->current_image->imgts); - cam->imgs.image_preview.diffs = 0; - } - - event(cam, EVENT_END, NULL, NULL, NULL, &cam->current_image->imgts); - dbse_exec(cam, NULL, 0, &cam->current_image->imgts, "event_end"); - - } - } else { - movie_free(cam->movie_norm); - cam->movie_norm = NULL; - - movie_free(cam->movie_motion); - cam->movie_motion = NULL; - - movie_free(cam->movie_timelapse); - cam->movie_timelapse = NULL; - - if (cam->dbsemp != NULL) { - cam->dbsemp->database_sqlite3 = NULL; + event(cam, EVENT_TLAPSE_END, NULL, NULL, NULL, NULL); + if (cam->event_nr == cam->prev_event) { + mlp_ring_process(cam); + if (cam->imgs.image_preview.diffs) { + event(cam, EVENT_IMAGE_PREVIEW, NULL, NULL, NULL, &cam->current_image->imgts); + cam->imgs.image_preview.diffs = 0; } + event(cam, EVENT_END, NULL, NULL, NULL, &cam->current_image->imgts); + dbse_exec(cam, NULL, 0, &cam->current_image->imgts, "event_end"); } webu_stream_deinit(cam); diff --git a/src/motionplus.cpp b/src/motionplus.cpp index dd5f74c3..1fc8ebef 100644 --- a/src/motionplus.cpp +++ b/src/motionplus.cpp @@ -107,6 +107,7 @@ static void sig_handler(int signo) exit(0); case SIGVTALRM: printf("SIGVTALRM went off\n"); + pthread_exit(NULL); break; } } @@ -462,113 +463,97 @@ static void motion_restart(struct ctx_motapp *motapp, int argc, char **argv) } /* Check for whether any cams are locked */ -static void motion_watchdog(struct ctx_motapp *motapp, int indx) +static void motion_watchdog(struct ctx_motapp *motapp, int camindx) { + int indx; - /* Notes: - * To test scenarios, just double lock a mutex in a spawned thread. - * We use detached threads because pthread_join would lock the main thread - * If we only call the first pthread_cancel when we reach the watchdog_kill - * it does not break us out of the mutex lock. - * We keep sending VTAlarms so the pthread_cancel queued can be caught. - * The calls to pthread_kill 'may' not work or cause crashes - * The cancel could finish and then the pthread_kill could be called - * on the invalid thread_id which could cause undefined results - * Even if the cancel finishes it is not clean since memory is not cleaned. - * The other option instead of cancel would be to exit(1) and terminate everything - * Best to just not get into a watchdog situation... - */ - - int sec_cancel, sec_kill; - - sec_cancel = 0 -motapp->cam_list[indx]->conf->watchdog_kill; - sec_kill = 2 * sec_cancel; - - if (!motapp->cam_list[indx]->running_cam) { + if (motapp->cam_list[camindx]->running_cam == false) { return; } - motapp->cam_list[indx]->watchdog--; - if (motapp->cam_list[indx]->watchdog == 0) { - MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO - ,_("Camera %d - Watchdog timeout. Trying to do a graceful restart") - , motapp->cam_list[indx]->camera_id); - motapp->cam_list[indx]->event_stop = true; /* Trigger end of event */ - motapp->cam_list[indx]->finish_cam = true; + motapp->cam_list[camindx]->watchdog--; + if (motapp->cam_list[camindx]->watchdog > 0) { + return; + } + + MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO + , _("Camera %d - Watchdog timeout.") + , motapp->cam_list[camindx]->camera_id); + + /* Shut down all the cameras */ + indx = 1; + while (motapp->cam_list[indx] != NULL) { + pthread_mutex_unlock(&motapp->mutex_camlst); + pthread_mutex_unlock(&motapp->mutex_parms); + pthread_mutex_unlock(&motapp->mutex_camlst); + pthread_mutex_unlock(&motapp->mutex_post); + pthread_mutex_unlock(&motapp->mutex_sqlite); + pthread_mutex_unlock(&motapp->global_lock); + pthread_mutex_unlock(&motapp->cam_list[indx]->stream.mutex); + pthread_mutex_unlock(&motapp->cam_list[indx]->parms_lock); + if ((motapp->cam_list[indx]->camera_type == CAMERA_TYPE_NETCAM) && (motapp->cam_list[indx]->netcam != NULL)) { + pthread_mutex_unlock(&motapp->cam_list[indx]->netcam->mutex); + pthread_mutex_unlock(&motapp->cam_list[indx]->netcam->mutex_pktarray); + pthread_mutex_unlock(&motapp->cam_list[indx]->netcam->mutex_transfer); motapp->cam_list[indx]->netcam->finish = true; } if ((motapp->cam_list[indx]->camera_type == CAMERA_TYPE_NETCAM) && (motapp->cam_list[indx]->netcam_high != NULL)) { + pthread_mutex_unlock(&motapp->cam_list[indx]->netcam_high->mutex); + pthread_mutex_unlock(&motapp->cam_list[indx]->netcam_high->mutex_pktarray); + pthread_mutex_unlock(&motapp->cam_list[indx]->netcam_high->mutex_transfer); motapp->cam_list[indx]->netcam_high->finish = true; } + motapp->cam_list[indx]->event_stop = true; + motapp->cam_list[indx]->finish_cam = true; + indx++; } - if (motapp->cam_list[indx]->watchdog == sec_cancel) { - MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO - ,_("Camera %d - Watchdog timeout. Requesting cancel.") - , motapp->cam_list[indx]->camera_id); - if ((motapp->cam_list[indx]->camera_type == CAMERA_TYPE_NETCAM) && - (motapp->cam_list[indx]->netcam != NULL)) { - if (motapp->cam_list[indx]->netcam->handler_finished == false) { - pthread_cancel(motapp->cam_list[indx]->netcam->thread_id); - } - } - if ((motapp->cam_list[indx]->camera_type == CAMERA_TYPE_NETCAM) && - (motapp->cam_list[indx]->netcam_high != NULL)) { - if (motapp->cam_list[indx]->netcam_high->handler_finished == false) { - pthread_cancel(motapp->cam_list[indx]->netcam_high->thread_id); - } - } - pthread_cancel(motapp->cam_list[indx]->thread_id); - } + SLEEP(motapp->cam_list[camindx]->conf->watchdog_kill, 0); - if (motapp->cam_list[indx]->watchdog < sec_kill) { - MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO - ,_("Camera %d - Watchdog timeout. Requesting kill.") - , motapp->cam_list[indx]->camera_id); - if ((motapp->cam_list[indx]->camera_type == CAMERA_TYPE_NETCAM) && - (motapp->cam_list[indx]->netcam != NULL)) { + /* When in a watchdog timeout and we get to a kill situation, + * we WILL have to leak memory because the freeing/deinit + * processes could lock this thread which would stop everything. + */ + indx = 1; + while (motapp->cam_list[indx] != NULL) { + if (motapp->cam_list[indx]->netcam != NULL) { if (motapp->cam_list[indx]->netcam->handler_finished == false) { + MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO + , _("Camera %d - Watchdog netcam kill.") + , motapp->cam_list[indx]->camera_id); pthread_kill(motapp->cam_list[indx]->netcam->thread_id, SIGVTALRM); } - motapp->threads_running--; - netcam_cleanup(motapp->cam_list[indx],false); } - if ((motapp->cam_list[indx]->camera_type == CAMERA_TYPE_NETCAM) && - (motapp->cam_list[indx]->netcam_high != NULL)) { + if (motapp->cam_list[indx]->netcam_high != NULL) { if (motapp->cam_list[indx]->netcam_high->handler_finished == false) { + MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO + , _("Camera %d - Watchdog netcam_high kill.") + , motapp->cam_list[indx]->camera_id); pthread_kill(motapp->cam_list[indx]->netcam_high->thread_id, SIGVTALRM); } - motapp->cam_list[indx]->netcam_high->handler_finished = true; - motapp->threads_running--; - netcam_cleanup(motapp->cam_list[indx], false); } - if (motapp->cam_list[indx]->running_cam) { - pthread_kill(motapp->cam_list[indx]->thread_id,SIGVTALRM); - } - MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO - ,_("Camera %d - Cleaning thread.") - , motapp->cam_list[indx]->camera_id); - motapp->threads_running--; - mlp_cleanup(motapp->cam_list[indx]); + if (motapp->cam_list[indx]->running_cam == true) { + MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO + , _("Camera %d - Watchdog kill.") + , motapp->cam_list[indx]->camera_id); + pthread_kill(motapp->cam_list[indx]->thread_id, SIGVTALRM); + }; motapp->cam_list[indx]->running_cam = false; - motapp->cam_list[indx]->finish_cam = false; + motapp->cam_list[indx]->restart_cam = false; + indx++; } + motapp->restart_all = true; + motapp->finish_all = true; + motapp->webcontrol_finish = true; + motapp->threads_running = 0; } static int motion_check_threadcount(struct ctx_motapp *motapp) { - /* Return 1 if we should break out of loop */ - - /* It has been observed that this is not counting every - * thread running. The netcams spawn handler threads which are not - * counted here. This is only counting ctx_cam threads and when they - * all get to zero, then we are done. - */ - int thrdcnt, indx; thrdcnt = 0; @@ -699,6 +684,7 @@ static void motion_cam_delete(struct ctx_motapp *motapp) /* Delete the config context */ delete motapp->cam_list[motapp->cam_delete]->conf; delete motapp->cam_list[motapp->cam_delete]; + motapp->cam_list[motapp->cam_delete] = NULL; /* Set up a new cam_list */ tmp = (struct ctx_cam **)mymalloc(sizeof(struct ctx_cam *) * indx_cam); @@ -766,8 +752,8 @@ int main (int argc, char **argv) for (indx = (motapp->cam_list[1] != NULL ? 1 : 0); motapp->cam_list[indx]; indx++) { /* Check if threads wants to be restarted */ - if ((!motapp->cam_list[indx]->running_cam) && - (motapp->cam_list[indx]->restart_cam)) { + if ((motapp->cam_list[indx]->running_cam == false) && + (motapp->cam_list[indx]->restart_cam == true)) { MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO ,_("Motion camera %d restart") , motapp->cam_list[indx]->camera_id); diff --git a/src/netcam.cpp b/src/netcam.cpp index 92dfe910..e6b0d569 100644 --- a/src/netcam.cpp +++ b/src/netcam.cpp @@ -2184,24 +2184,28 @@ int netcam_setup(struct ctx_cam *cam) } +/* netcam_next (Called from the motion loop thread) */ int netcam_next(struct ctx_cam *cam, struct ctx_image_data *img_data) { + if (cam == NULL) { + return 1; + } - /* This is called from the motion loop thread */ - - if ((cam->netcam->status == NETCAM_RECONNECTING) || - (cam->netcam->status == NETCAM_NOTCONNECTED)) { + if (cam->netcam != NULL) { + if ((cam->netcam->status == NETCAM_RECONNECTING) || + (cam->netcam->status == NETCAM_NOTCONNECTED)) { return 1; } - pthread_mutex_lock(&cam->netcam->mutex); - netcam_pktarray_resize(cam, false); - memcpy(img_data->image_norm - , cam->netcam->img_latest->ptr - , cam->netcam->img_latest->used); - img_data->idnbr_norm = cam->netcam->idnbr; - pthread_mutex_unlock(&cam->netcam->mutex); + pthread_mutex_lock(&cam->netcam->mutex); + netcam_pktarray_resize(cam, false); + memcpy(img_data->image_norm + , cam->netcam->img_latest->ptr + , cam->netcam->img_latest->used); + img_data->idnbr_norm = cam->netcam->idnbr; + pthread_mutex_unlock(&cam->netcam->mutex); + } - if (cam->netcam_high) { + if (cam->netcam_high != NULL) { if ((cam->netcam_high->status == NETCAM_RECONNECTING) || (cam->netcam_high->status == NETCAM_NOTCONNECTED)) { return 1; diff --git a/src/rotate.cpp b/src/rotate.cpp index 385bb422..39d62eab 100644 --- a/src/rotate.cpp +++ b/src/rotate.cpp @@ -316,6 +316,10 @@ int rotate_map(struct ctx_cam *cam, struct ctx_image_data *img_data) unsigned char *img; unsigned char *temp_buff; + if (cam->rotate_data == NULL) { + return 0; + } + if (cam->rotate_data->degrees == 0 && cam->rotate_data->axis == FLIP_TYPE_NONE) { return 0; }