示例#1
0
/**
 * This is the main worker process.
 * Takes tasks from the queue in a loop and processes them by calling the registered callbacks.
 * @param id - id of the worker
 * @returns never, exits on shutdown.
 */
void worker_process(int id) {
    task_t t;
    cdp_cb_t *cb;
    int r;
    LM_INFO("[%d] Worker process started...\n", id);
    /* init the application level for this child */
    while (1) {
        if (shutdownx && (*shutdownx)) break;
	cfg_update();
        t = take_task();
        if (!t.msg) {
            if (shutdownx && (*shutdownx)) break;
            LM_INFO("[%d] got empty task Q(%d/%d)\n", id, tasks->start, tasks->end);
            continue;
        }
        LM_DBG("worker_process(): [%d] got task Q(%d/%d)\n", id, tasks->start, tasks->end);
        r = is_req(t.msg);
        for (cb = callbacks->head; cb; cb = cb->next)
            (*(cb->cb))(t.p, t.msg, *(cb->ptr));

        if (r) {
            AAAFreeMessage(&(t.msg));
        } else {
            /* will be freed by the user in upper api */
            /*AAAFreeMessage(&(t.msg));*/
        }
    }
    worker_poison_queue();
    LM_INFO("[%d]... Worker process finished\n", id);
#ifdef CDP_FOR_SER
#else
#ifdef PKG_MALLOC
    LM_DBG("Worker[%d] Memory status (pkg):\n", id);
    //pkg_status();
#ifdef pkg_sums
    pkg_sums();
#endif
#endif
    dp_del_pid(getpid());
#endif
    exit(0);
}
/**
 * Shutdown the CDiameterPeer nicely.
 * It stops the workers, disconnects peers, drops timers and wait for all processes to exit.
 */
void diameter_peer_destroy()
{
	int pid,status;
	handler *h;
	
	lock_get(shutdownx_lock);
	if (*shutdownx) {
		/* already other process is cleaning stuff */
		lock_release(shutdownx_lock);			
		return;
	}else {
		/* indicating that we are shuting down */
		*shutdownx = 1;
		lock_release(shutdownx_lock);
	}


	worker_poison_queue();

	/* wait for all childs to clean up nicely (acceptor, receiver, timer, workers) */
	LOG(L_INFO,"INFO:destroy_diameter_peer(): Terminating all childs...\n");
	while(pid_list->tail){
		pid = dp_last_pid();
		if (pid<=0||pid==getpid()){
			dp_del_pid(pid);
			continue;
		}
		LOG(L_INFO,"INFO:destroy_diameter_peer(): Waiting for child [%d] to terminate...\n",pid);
		if (waitpid(pid,&status,0)<0){
			dp_del_pid(pid);
			continue;
		}
		if (!WIFEXITED(status) /*|| WIFSIGNALED(status)*/){
			worker_poison_queue();
			sleep(1);			
		} else {
			dp_del_pid(pid);
		}

	}
	LOG(L_INFO,"INFO:destroy_diameter_peer(): All processes terminated. Cleaning up.\n");
	
	/* clean upt the timer */
	timer_cdp_destroy();
	
	/* cleaning up workers */
	worker_destroy();
	
	/* cleaning peer_manager */
	peer_manager_destroy();
	
	/* cleaning up sessions */
	session_destroy();

	/* cleaning up global vars */
/*	lock_get(pid_list_lock);*/
	shm_free(dp_first_pid);
	shm_free(pid_list);
	lock_destroy(pid_list_lock);
	lock_dealloc((void*)pid_list_lock);
	
	shm_free(shutdownx);
	
	lock_destroy(shutdownx_lock);
	lock_dealloc((void*)shutdownx_lock);
	
	lock_get(handlers_lock);
	while(handlers->head){
		h = handlers->head->next;
		shm_free(handlers->head);
		handlers->head = h;
	}
	lock_destroy(handlers_lock);
	lock_dealloc((void*)handlers_lock);
	shm_free(handlers);
		
	free_dp_config(config);	
	LOG(L_CRIT,"INFO:destroy_diameter_peer(): Bye Bye from C Diameter Peer test\n");

#ifndef CDP_FOR_SER
	#ifdef PKG_MALLOC
		LOG(memlog, "Memory status (pkg):\n");
		//pkg_status();
		#ifdef pkg_sums
			pkg_sums();
		#endif 
	#endif
	#ifdef SHM_MEM
		LOG(memlog, "Memory status (shm):\n");
		//shm_status();
		#ifdef shm_sums
			shm_sums();
		#endif 
		/* zero all shmem alloc vars that we still use */
		shm_mem_destroy();
	#endif
#endif	
}