www.pudn.com > webcam_server-0.50.rar > watchdog.c


/*********************************************************************
 * webcam_server                                                     *
 *                                                                   *
 * (c) 2002 Donn Morrison donn@donn.dyndns.org                       *
 *                                                                   *
 * code used from Gerd Knorr's xawtv (libng)                         *
 * - and -                                                           *
 * Cory Lueninghoener's gqcam                                        *
 *                                                                   *
 *    waits for connections from a viewer and sends                  *
 *    jpeg encoded captures as a live video feed                     *
 *                                                                   *
 *********************************************************************/

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "webcam_server.h"
#include "grabber.h"
#include "client.h"
#include "camera.h"
#include "imgqueue.h"

#define MAX_WATCHDOG_RETRIES	5	/* max watchdog retries */

/*-----------------------------------------------------------
  watchdog_thread
  - simulates a client connection and ensures the grabber
    thread is working. this is a quick hack to unstick
    dead read()s
  -----------------------------------------------------------*/
int watchdog_thread(struct caminfo *cam)
{
	struct imagequeue *ptr;
	int last_id = -1;
	int tries = 0;
	int res;
	char buff[256];
	
	while(1)
	{
		/* simulate a client connection */
		sem_post(&cam->sem_con);
		
		/* get the latest image */
		pthread_mutex_lock(&cam->lock_queue);
		ptr = peek(cam);
		if(!ptr)
		{
			/* no images available */
			pthread_mutex_unlock(&cam->lock_queue);
		}
		else
		{
			pthread_mutex_lock(&ptr->lock_ref);
			ptr->ref++;
			pthread_mutex_unlock(&ptr->lock_ref);

			pthread_mutex_unlock(&cam->lock_queue);

			if(ptr->id == last_id)
			{
				/* hmm...same id as last time */
				tries++;
				sprintf(buff,"watchdog: image (%d) was the same as last time! %d/%d\n",
					last_id, tries, MAX_WATCHDOG_RETRIES);
				log(cam,buff);
			}
			else
			{
				last_id = ptr->id;
				tries = 0;
			}
			
			pthread_mutex_lock(&ptr->lock_ref);
			ptr->ref--;
			pthread_mutex_unlock(&ptr->lock_ref);
		}
		
		if(tries == MAX_WATCHDOG_RETRIES)
		{
			log(cam,"watchdog: ERROR: grabber thread suspected stuck\n");
			/* drastic action!
			 * we assume the grabber thread is stuck
			 * on a read, and we kill it, reinit the
			 * camera, and restart the grabber thread
			 */
			tries = 0;
			last_id = -1;
			
			log(cam,"watchdog: killing grabber thread\n");
			pthread_cancel(cam->pt_grab);
			
			usleep(1000000);
			
			log(cam,"watchdog: closing camera\n");
			if(close_cam(cam) > -1)			
				log(cam,"watchdog: camera closed\n");
			usleep(5000000);
			
			log(cam,"watchdog: re-initing camera\n");
			res = open_cam(cam, cam->o.devfile);
			
			while(res < 0 && cam->o.retry_init)
			{
				log(cam,"watchdog: re-init failed, retrying\n");
				usleep(1000000);
				res = open_cam(cam, cam->o.devfile);
			}

			if(res < 0)
			{
				log(cam,"watchdog: re-init failed, exiting\n");
				exit(1);
			}

			sprintf(buff, "watchdog: re-init ok: %d\n", res);
			log(cam,buff);
			
			log(cam,"watchdog: setting camera defaults\n");
			/* get camera defaults */
			get_cam_info(cam);
			cam->vid_win.width = cam->o.width;
			cam->vid_win.height = cam->o.height;
			if(set_cam_info(cam) < 0)
			{
				get_cam_info(cam);
				if(set_cam_info(cam) < 0)
				{
					exit(1);
				}
			}
			cam->o.width = cam->vid_win.width;
			cam->o.height = cam->vid_win.height;
			
			log(cam,"watchdog: restarting grab_thread\n");
			cam->grab_thread_alive = 1;
			pthread_create(&cam->pt_grab, NULL, (void*)grab_thread, (void *)cam);
			pthread_detach(cam->pt_grab);
		}
		
		sem_wait(&cam->sem_con);
		
		/* sleep and then check again */
		usleep(2000000);
	}
}