コード例 #1
0
ファイル: proc_threads_queues.c プロジェクト: p1rate5s/c-icap
int put_to_queue(struct connections_queue *q,ci_connection_t *con){
     int ret;
     if(ci_thread_mutex_lock(&(q->queue_mtx))!=0)
	  return -1;
     if(q->used==q->size){
	  ci_thread_mutex_unlock(&(q->queue_mtx));
	  ci_debug_printf(1,"put_to_queue_fatal error used=%d size=%d\n",q->used,q->size);
	  return 0;
     }
     memcpy(&(q->connections[q->used]),con,sizeof(ci_connection_t));
     ret=++q->used;
     ci_thread_mutex_unlock(&(q->queue_mtx));
     ci_thread_cond_signal(&(q->queue_cond)); //????
     return ret;
}
コード例 #2
0
void unBusyCascade(ImageCategory *category, LinkedCascade *item)
{
int need_signal = 0;

	if(item == NULL || category->freeing_category) return;

	if(ci_thread_mutex_lock(&category->mutex) != 0)
	{
		ci_debug_printf(1, "unBusyCascade: failed to lock\n");
	}

        if(!category->free_cascade) need_signal = 1;

	// Add item back to free list
	item->next = category->free_cascade;
	category->free_cascade = item;

	// Clean up and return
	if(need_signal) ci_thread_cond_signal(&category->cond);

	ci_thread_mutex_unlock(&category->mutex);
}
コード例 #3
0
ファイル: mpmt_server.c プロジェクト: p1rate5s/c-icap
void child_main(int sockfd, int pipefd)
{
     ci_thread_t thread;
     int i, ret;

     signal(SIGTERM, SIG_IGN);  /*Ignore parent requests to kill us untill we are up and running */
     ci_thread_mutex_init(&threads_list_mtx);
     ci_thread_mutex_init(&counters_mtx);
     ci_thread_cond_init(&free_server_cond);
     
     ci_stat_attach_mem(child_data->stats, child_data->stats_size, NULL);

     threads_list =
         (server_decl_t **) malloc((CONF.THREADS_PER_CHILD + 1) *
                                   sizeof(server_decl_t *));
     con_queue = init_queue(CONF.THREADS_PER_CHILD);

     for (i = 0; i < CONF.THREADS_PER_CHILD; i++) {
          if ((threads_list[i] = newthread(con_queue)) == NULL) {
               exit(-1);        // FATAL error.....
          }
          ret =
              ci_thread_create(&thread, (void *(*)(void *)) thread_main,
                               (void *) threads_list[i]);
          threads_list[i]->srv_pthread = thread;
     }
     threads_list[CONF.THREADS_PER_CHILD] = NULL;
     /*Now start the listener thread.... */
     ret = ci_thread_create(&thread, (void *(*)(void *)) listener_thread,
                            (void *) &sockfd);
     listener_thread_id = thread;
     
     /*set srand for child......*/
     srand(((unsigned int)time(NULL)) + (unsigned int)getpid());
     /*I suppose that all my threads are up now. We can setup our signal handlers */
     child_signals();

     /* A signal from parent may comes while we are starting.
        Listener will not accept any request in this case, (it checks on 
        the beggining of the accept loop for parent commands) so we can 
        shutdown imediatelly even if the parent said gracefuly.*/
     if (child_data->father_said)
         child_data->to_be_killed = IMMEDIATELY;

     /*start child commands may have non thread safe code but the worker threads
       does not serving requests yet.*/
     commands_execute_start_child();

     /*Signal listener to start accepting requests.*/
     int doStart = 0;
     do {
         ci_thread_mutex_lock(&counters_mtx);
         doStart = listener_running;
         ci_thread_mutex_unlock(&counters_mtx);
         if (!doStart)
             ci_usleep(5);
     } while(!doStart);
     ci_thread_cond_signal(&free_server_cond);

     while (!child_data->to_be_killed) {
          char buf[512];
          int bytes;
          if ((ret = ci_wait_for_data(pipefd, 1, wait_for_read)) > 0) { /*data input */
               bytes = ci_read_nonblock(pipefd, buf, 511);
               if (bytes == 0) {
                    ci_debug_printf(1,
                                    "Parent closed the pipe connection! Going to term immediately!\n");
                    child_data->to_be_killed = IMMEDIATELY;
               } else {
                    buf[bytes] = '\0';
                    handle_child_process_commands(buf);
               }
          }
          else if (ret < 0) {
               ci_debug_printf(1,
                               "An error occured while waiting for commands from parent. Terminating!\n");
               child_data->to_be_killed = IMMEDIATELY;
          }
          if (!listener_running && !child_data->to_be_killed) {
               ci_debug_printf(1,
                               "Ohh!! something happened to listener thread! Terminating\n");
               child_data->to_be_killed = GRACEFULLY;
          }
          commands_exec_scheduled();
     }

     ci_debug_printf(5, "Child :%d going down :%s\n", getpid(),
                     child_data->to_be_killed == IMMEDIATELY? 
                     "IMMEDIATELY" : "GRACEFULLY");
     
     cancel_all_threads();
     commands_execute_stop_child();
     exit_normaly();
}
コード例 #4
0
ファイル: mpmt_server.c プロジェクト: p1rate5s/c-icap
int thread_main(server_decl_t * srv)
{
     ci_connection_t con;
     char clientname[CI_MAXHOSTNAMELEN + 1];
     int ret, request_status = CI_NO_STATUS;
     int keepalive_reqs;
//***********************
     thread_signals(0);
//*************************
     srv->srv_id = getpid();    //Setting my pid ...

     for (;;) {
          /*
             If we must shutdown IMEDIATELLY it is time to leave the server
             else if we are going to shutdown GRACEFULLY we are going to die 
             only if there are not any accepted connections
           */
          if (child_data->to_be_killed == IMMEDIATELY) {
               srv->running = 0;
               return 1;
          }

          if ((ret = get_from_queue(con_queue, &con)) == 0) {
               if (child_data->to_be_killed) {
                    srv->running = 0;
                    return 1;
               }
               ret = wait_for_queue(con_queue);
               continue;
          }

          if (ret < 0) {        //An error has occured
               ci_debug_printf(1,
                               "Fatal Error!!! Error getting a connection from connections queue!!!\n");
               break;
          }

          ci_thread_mutex_lock(&counters_mtx);  /*Update counters as soon as possible */
          (child_data->freeservers)--;
          (child_data->usedservers)++;
          ci_thread_mutex_unlock(&counters_mtx);

          ci_netio_init(con.fd);
          ret = 1;
          if (srv->current_req == NULL)
               srv->current_req = newrequest(&con);
          else
               ret = recycle_request(srv->current_req, &con);

          if (srv->current_req == NULL || ret == 0) {
               ci_sockaddr_t_to_host(&(con.claddr), clientname,
                                     CI_MAXHOSTNAMELEN);
               ci_debug_printf(1, "Request from %s denied...\n", clientname);
               hard_close_connection((&con));
               goto end_of_main_loop_thread;    /*The request rejected. Log an error and continue ... */
          }

          keepalive_reqs = 0;
          do {
               if (MAX_KEEPALIVE_REQUESTS > 0
                   && keepalive_reqs >= MAX_KEEPALIVE_REQUESTS)
                    srv->current_req->keepalive = 0;    /*do not keep alive connection */
               if (child_data->to_be_killed)    /*We are going to die do not keep-alive */
                    srv->current_req->keepalive = 0;

               if ((request_status = process_request(srv->current_req)) == CI_NO_STATUS) {
                    ci_debug_printf(5,
                                    "Process request timeout or interrupted....\n");
                    ci_request_reset(srv->current_req);
                    break;
               }
               srv->served_requests++;
               srv->served_requests_no_reallocation++;
               keepalive_reqs++;

               /*Increase served requests. I dont like this. The delay is small but I don't like... */
               ci_thread_mutex_lock(&counters_mtx);
               (child_data->requests)++;
               ci_thread_mutex_unlock(&counters_mtx);

               log_access(srv->current_req, request_status);
//             break; //No keep-alive ......

               if (child_data->to_be_killed  == IMMEDIATELY)
                    break;      //Just exiting the keep-alive loop

               /*if we are going to term gracefully we will try to keep our promice for
                 keepalived request....
                */
               if (child_data->to_be_killed  == GRACEFULLY && 
                   srv->current_req->keepalive == 0)
                    break;

               ci_debug_printf(8, "Keep-alive:%d\n",
                               srv->current_req->keepalive);
               if (srv->current_req->keepalive && keepalive_request(srv->current_req)) {
                   ci_debug_printf(8,
                                   "Server %d going to serve new request from client (keep-alive) \n",
                                   srv->srv_id);
               }
               else
                    break;
          } while (1);

          if (srv->current_req) {
               if (request_status != CI_OK || child_data->to_be_killed) {
                    hard_close_connection(srv->current_req->connection);
               }
               else {
                    close_connection(srv->current_req->connection);
               }
          }
          if (srv->served_requests_no_reallocation >
              MAX_REQUESTS_BEFORE_REALLOCATE_MEM) {
               ci_debug_printf(5,
                               "Max requests reached, reallocate memory and buffers .....\n");
               ci_request_destroy(srv->current_req);
               srv->current_req = NULL;
               srv->served_requests_no_reallocation = 0;
          }


        end_of_main_loop_thread:
          ci_thread_mutex_lock(&counters_mtx);
          (child_data->freeservers)++;
          (child_data->usedservers)--;
          ci_thread_mutex_unlock(&counters_mtx);
          ci_thread_cond_signal(&free_server_cond);

     }
     srv->running = 0;
     return 0;
}
コード例 #5
0
ファイル: mpmt_server.c プロジェクト: p1rate5s/c-icap
static void cancel_all_threads()
{
     int i = 0;
     int wait_listener_time = 10000;
     int wait_for_workers = CHILD_SHUTDOWN_TIMEOUT>5?CHILD_SHUTDOWN_TIMEOUT:5;
     int servers_running;
     /*Cancel listener thread .... */
     /*we are going to wait maximum about 10 ms */
     while (wait_listener_time > 0 && listener_running != 0) {
          /*Interrupt listener if it is waiting for threads or 
             waiting to accept new connections */
#ifdef SINGLE_ACCEPT
          pthread_cancel(listener_thread_id);   /*..... */
#else
          pthread_kill(listener_thread_id, SIGHUP);
#endif
          ci_thread_cond_signal(&free_server_cond);
          ci_usleep(1000);
          wait_listener_time -= 10;
     }
     if (listener_running == 0) {
          ci_debug_printf(5,
                          "Going to wait for the listener thread (pid: %d) to exit!\n",
                          threads_list[0]->srv_id);
          ci_thread_join(listener_thread_id);
          ci_debug_printf(5, "OK, cancelling the listener thread (pid: %d)!\n",
                          threads_list[0]->srv_id);
     }
     else {
          /*f**k the listener! going down ..... */
     }

     /*We are going to interupt the waiting for queue childs.
        We are going to wait threads which serve a request. */
     ci_thread_cond_broadcast(&(con_queue->queue_cond));
     /*wait for a milisecond*/
     ci_usleep(1000);
     servers_running = CONF.THREADS_PER_CHILD;
     while (servers_running && wait_for_workers >= 0) {
         /*child_data->to_be_killed, may change while we are inside this loop*/
         if (child_data->to_be_killed == IMMEDIATELY) {
             CHILD_HALT = 1;
         }
         for (i=0; i<CONF.THREADS_PER_CHILD; i++) {
             if (threads_list[i] != NULL) { /* if the i thread is still alive*/
                 if (!threads_list[i]->running) { /*if the i thread is not running any more*/
                     ci_debug_printf(5, "Cancel server %d, thread_id %lu (%d)\n",
                                     threads_list[i]->srv_id, threads_list[i]->srv_pthread,
                                     i);
                     ci_thread_join(threads_list[i]->srv_pthread);
                     release_thread_i(i);
                     servers_running --;
                 }
                 else if (child_data->to_be_killed == IMMEDIATELY){ 
                     /*The thread is still running, and we have a timeout for waiting 
                       the thread to exit. */
                     if (wait_for_workers <= 2) {
                         ci_debug_printf(5, "Thread %ld still running near the timeout. Try to kill it\n", threads_list[i]->srv_pthread);
                         pthread_kill( threads_list[i]->srv_pthread, SIGTERM);
                     }
                 }
             }/*the i thread is still alive*/
         } /* for(i=0;i< CONF.THREADS_PER_CHILD;i++)*/

         /*wait for 1 second for the next round*/
         ci_usleep(999999);

         /*
           The child_data->to_be_killed may change while we are running this function.
           In the case it has/got the value IMMEDIATELY decrease wait_for_workers:
         */
         if (child_data->to_be_killed == IMMEDIATELY)
             wait_for_workers --;
         
     } /* while(servers_running)*/

     if (servers_running) {
         ci_debug_printf(5, "Not all the servers canceled. Anyway exiting....\n");
     }
     else {
         ci_debug_printf(5, "All servers canceled\n");
         free(threads_list);
     }
}
コード例 #6
0
ファイル: mpmt_server.c プロジェクト: p1rate5s/c-icap
int thread_main(server_decl_t *srv){
     ci_connection_t con;
     ci_thread_mutex_t cont_mtx;
     char clientname[CI_MAXHOSTNAMELEN+1];
     int max,ret,request_status=0;
     request_t *tmp;
//***********************
     thread_signals();
//*************************
     srv->srv_id=getpid(); //Setting my pid ...
     srv->srv_pthread=pthread_self();

     for(;;){
	  if(child_data->to_be_killed)
	       return; //Exiting thread.....
	  
	  if((ret=get_from_queue(con_queue,&con))==0){
	       wait_for_queue(con_queue); //It is better that the wait_for_queue to be 
                                          //moved into the get_from_queue 
	       continue; 
	  }
	  ci_thread_mutex_lock(&counters_mtx);
	  (child_data->freeservers)--;
	  (child_data->usedservers)++;
	  ci_thread_mutex_unlock(&counters_mtx);


	  if(ret<0){ //An error has occured
	       debug_printf(1,"Error getting from connections queue\n");
	       break;
	  }

/*
	  icap_addrtohost(&(con.claddr.sin_addr),clientname, CI_MAXHOSTNAMELEN);
	  debug_printf(1,"Client name: %s server %d\n",clientname,srv->srv_id);
*/
	  icap_netio_init(con.fd);

	  if(srv->current_req==NULL)
	       srv->current_req=newrequest(&con);
	  else
	       recycle_request(srv->current_req,&con);

	  do{
	       if((request_status=process_request(srv->current_req))<0){
		    debug_printf(5,"Process request timeout or interupted....\n");
		    reset_request(srv->current_req);
		    break;//
	       }
	       srv->served_requests++;
	       srv->served_requests_no_reallocation++;

    /*Increase served requests. I dont like this. The delay is small but I don't like...*/
	       ci_thread_mutex_lock(&counters_mtx); 
	       (child_data->requests)++; 
	       ci_thread_mutex_unlock(&counters_mtx);



	       log_access(srv->current_req,request_status);
//	       break; //No keep-alive ......

	       if(child_data->to_be_killed)
		    return; //Exiting thread.....
	      
               debug_printf(8,"Keep-alive:%d\n",srv->current_req->keepalive); 
	       if(srv->current_req->keepalive && check_for_keepalive_data(srv->current_req->connection->fd)){
		    reset_request(srv->current_req);
		    debug_printf(8,"Server %d going to serve new request from client(keep-alive) \n",
				 srv->srv_id);
	       }
	       else
		    break;
	  }while(1);
	  
	  if(srv->current_req){
	       if(request_status<0)
		    hard_close_connection(srv->current_req->connection);
	       else
		    close_connection(srv->current_req->connection);
	  }
	  if(srv->served_requests_no_reallocation > MAX_REQUESTS_BEFORE_REALLOCATE_MEM){
	       debug_printf(5,"Max requests reached, reallocate memory and buffers .....\n");
	       destroy_request(srv->current_req);
	       srv->current_req=NULL;
	       srv->served_requests_no_reallocation=0;
	  }

	  ci_thread_mutex_lock(&counters_mtx);
	  (child_data->freeservers)++;
	  (child_data->usedservers)--;
	  ci_thread_mutex_unlock(&counters_mtx);
	  ci_thread_cond_signal(&free_server_cond);

     }
     return 0;
}