int wait_for_queue(struct connections_queue *q){ ci_debug_printf(7,"Waiting for a request....\n"); if(ci_thread_mutex_lock(&(q->cond_mtx))!=0) return -1; if(ci_thread_cond_wait(&(q->queue_cond),&(q->cond_mtx))!=0){ ci_thread_mutex_unlock(&(q->cond_mtx)); return -1; } if(ci_thread_mutex_unlock(&(q->cond_mtx))!=0) return -1; return 1; }
LinkedCascade *getFreeCascade(ImageCategory *category) { LinkedCascade *item = NULL; if(category->freeing_category) return NULL; ci_thread_mutex_lock(&category->mutex); while(!category->free_cascade) { ci_thread_cond_wait(&category->cond, &category->mutex); } // Ok, we should have a free cascade: // Remove free cascade item from free list item = category->free_cascade; category->free_cascade = item->next; ci_thread_mutex_unlock(&category->mutex); return item; // Tell caller the cascade }
void listener_thread(int *fd) { ci_connection_t conn; socklen_t claddrlen = sizeof(struct sockaddr_in); int haschild = 1, jobs_in_queue = 0; int pid, sockfd; sockfd = *fd; thread_signals(1); /*Wait main process to signal us to start accepting requests*/ ci_thread_mutex_lock(&counters_mtx); listener_running = 1; ci_thread_cond_wait(&free_server_cond, &counters_mtx); ci_thread_mutex_unlock(&counters_mtx); pid = getpid(); for (;;) { //Global for if (child_data->to_be_killed) { ci_debug_printf(5, "Listener of pid:%d exiting!\n", pid); goto LISTENER_FAILS_UNLOCKED; } if (!ci_proc_mutex_lock(&accept_mutex)) { if (errno == EINTR) { ci_debug_printf(5, "proc_mutex_lock interrupted (EINTR received, pid=%d)!\n", pid); /*Try again to take the lock */ continue; } else { ci_debug_printf(1, "Unknown errno %d in proc_mutex_lock of pid %d. Exiting!\n", errno, pid); goto LISTENER_FAILS_UNLOCKED; } } child_data->idle = 0; ci_debug_printf(7, "Child %d getting requests now ...\n", pid); do { //Getting requests while we have free servers..... #ifndef SINGLE_ACCEPT fd_set fds; int ret; do { FD_ZERO(&fds); FD_SET(sockfd, &fds); errno = 0; ret = select(sockfd + 1, &fds, NULL, NULL, NULL); if (ret < 0) { if (errno != EINTR) { ci_debug_printf(1, "Error in select %d! Exiting server!\n", errno); goto LISTENER_FAILS; } if (child_data->to_be_killed) { ci_debug_printf(5, "Listener server signalled to exit!\n"); goto LISTENER_FAILS; } } } while (errno == EINTR); #endif do { errno = 0; claddrlen = sizeof(conn.claddr.sockaddr); if (((conn.fd = accept(sockfd, (struct sockaddr *) &(conn.claddr.sockaddr), &claddrlen)) == -1)) { if (errno != EINTR) { ci_debug_printf(1, "Error accept %d!\nExiting server!\n", errno); goto LISTENER_FAILS; } /*Here we are going to exit only if accept interrupted by a signal else if we accepted an fd we must add it to queue for processing. */ if (errno == EINTR && child_data->to_be_killed) { ci_debug_printf(5, "Listener server signalled to exit!\n"); goto LISTENER_FAILS; } } } while (errno == EINTR && !child_data->to_be_killed); claddrlen = sizeof(conn.srvaddr.sockaddr); getsockname(conn.fd, (struct sockaddr *) &(conn.srvaddr.sockaddr), &claddrlen); ci_fill_sockaddr(&conn.claddr); ci_fill_sockaddr(&conn.srvaddr); icap_socket_opts(sockfd, MAX_SECS_TO_LINGER); if ((jobs_in_queue = put_to_queue(con_queue, &conn)) == 0) { ci_debug_printf(1, "ERROR!!!!!! NO AVAILABLE SERVERS! THIS IS A BUG!!!!!!!!\n"); ci_debug_printf(1, "Jobs in Queue: %d, Free servers: %d, Used Servers: %d, Requests: %d\n", jobs_in_queue, child_data->freeservers, child_data->usedservers, child_data->requests); goto LISTENER_FAILS; } (child_data->connections)++; //NUM of Requests.... if (child_data->to_be_killed) { ci_debug_printf(5, "Listener server must exit!\n"); goto LISTENER_FAILS; } ci_thread_mutex_lock(&counters_mtx); haschild = ((child_data->freeservers - jobs_in_queue) > 0 ? 1 : 0); ci_thread_mutex_unlock(&counters_mtx); } while (haschild); ci_debug_printf(7, "Child %d STOPS getting requests now ...\n", pid); child_data->idle = 1; while (!ci_proc_mutex_unlock(&accept_mutex)) { if (errno != EINTR) { ci_debug_printf(1, "Error:%d while trying to unlock proc_mutex, exiting listener of server:%d\n", errno, pid); goto LISTENER_FAILS_UNLOCKED; } ci_debug_printf(5, "Mutex lock interrupted while trying to unlock proc_mutex, pid: %d\n", pid); } ci_thread_mutex_lock(&counters_mtx); if ((child_data->freeservers - connections_pending(con_queue)) <= 0) { ci_debug_printf(7, "Child %d waiting for a thread to accept more connections ...\n", pid); ci_thread_cond_wait(&free_server_cond, &counters_mtx); } ci_thread_mutex_unlock(&counters_mtx); } LISTENER_FAILS_UNLOCKED: listener_running = 0; return; LISTENER_FAILS: listener_running = 0; errno = 0; while (!ci_proc_mutex_unlock(&accept_mutex)) { if (errno != EINTR) { ci_debug_printf(1, "Error:%d while trying to unlock proc_mutex of server:%d\n", errno, pid); break; } ci_debug_printf(7, "Mutex lock interrupted while trying to unlock proc_mutex before terminating\n"); } return; }
void child_main(int sockfd){ ci_connection_t conn; int claddrlen=sizeof(struct sockaddr_in); ci_thread_t thread; char clientname[300]; int i,retcode,haschild=1,jobs_in_queue=0; int pid=0; child_signals(); pid=getpid(); ci_thread_mutex_init(&threads_list_mtx); ci_thread_mutex_init(&counters_mtx); ci_thread_cond_init(&free_server_cond); threads_list=(server_decl_t **)malloc((START_SERVERS+1)*sizeof(server_decl_t *)); con_queue=init_queue(START_SERVERS); for(i=0;i<START_SERVERS;i++){ if((threads_list[i]=newthread(con_queue))==NULL){ exit(-1);// FATAL error..... } retcode=ci_thread_create(&thread,(void *(*)(void *))thread_main,(void *)threads_list[i]); } threads_list[START_SERVERS]=NULL; for(;;){ //Global for if(!ci_proc_mutex_lock(&accept_mutex)){ if(errno==EINTR){ debug_printf(5,"EINTR received\n"); if(child_data->to_be_killed) goto end_child_main; continue; } } child_data->idle=0; debug_printf(7,"Child %d getting requests now ...\n",pid); do{//Getting requests while we have free servers..... do{ errno = 0; if(((conn.fd = accept(sockfd, (struct sockaddr *)&(conn.claddr), &claddrlen)) == -1) && errno != EINTR){ debug_printf(1,"error accept .... %d\nExiting server ....\n",errno); exit(-1); //For the moment ....... goto end_child_main ; } if(errno==EINTR && child_data->to_be_killed) goto end_child_main; }while(errno==EINTR); getsockname(conn.fd,(struct sockaddr *)&(conn.srvaddr),&claddrlen); icap_socket_opts(sockfd); if((jobs_in_queue=put_to_queue(con_queue,&conn))==0){ debug_printf(1,"ERROR!!!!!!NO AVAILABLE SERVERS!!!!!!!!!\n"); child_data->to_be_killed=GRACEFULLY; debug_printf(1,"Jobs in Queue:%d,Free servers:%d, Used Servers :%d, Requests %d\n", jobs_in_queue, child_data->freeservers,child_data->usedservers,child_data->requests); goto end_child_main; } ci_thread_mutex_lock(&counters_mtx); haschild=(child_data->freeservers?1:0); ci_thread_mutex_unlock(&counters_mtx); (child_data->connections)++; //NUM of Requests.... }while(haschild); child_data->idle=1; ci_proc_mutex_unlock(&accept_mutex); ci_thread_mutex_lock(&counters_mtx); if(child_data->freeservers==0){ debug_printf(7,"Child %d waiting for a thread to accept more connections ...\n",pid); ci_thread_cond_wait(&free_server_cond,&counters_mtx); } ci_thread_mutex_unlock(&counters_mtx); } end_child_main: cancel_all_threads(); exit_normaly(); }
int worker_main(ci_socket sockfd) { ci_connection_t conn; int claddrlen = sizeof(struct sockaddr_in); // char clientname[300]; int haschild = 1, jobs_in_queue = 0; int pid = 0, error; for (;;) { //Global for if (!ci_proc_mutex_lock(&accept_mutex)) { if (child_data->to_be_killed) return 1; continue; } child_data->idle = 0; pid = (int) child_data->pid; ci_debug_printf(1, "Child %d getting requests now ...\n", pid); do { //Getting requests while we have free servers..... ci_debug_printf(1, "In accept loop..................\n"); error = 0; if (((conn.fd = accept(sockfd, (struct sockaddr *) &(conn.claddr.sockaddr), &claddrlen)) == INVALID_SOCKET) && // if(((conn.fd = WSAAccept(sockfd, (struct sockaddr *)&(conn.claddr), &claddrlen,NULL,NULL)) == INVALID_SOCKET ) && (error = WSAGetLastError())) { ci_debug_printf(1, "error accept .... %d\nExiting server ....\n", error); exit(-1); //For the moment ....... } ci_debug_printf(1, "Accepting one connection...\n"); claddrlen = sizeof(conn.srvaddr.sockaddr); getsockname(conn.fd, (struct sockaddr *) &(conn.srvaddr.sockaddr), &claddrlen); ci_fill_sockaddr(&conn.claddr); ci_fill_sockaddr(&conn.srvaddr); icap_socket_opts(sockfd, MAX_SECS_TO_LINGER); if ((jobs_in_queue = put_to_queue(con_queue, &conn)) == 0) { ci_debug_printf(1, "ERROR!!!!!!NO AVAILABLE SERVERS!!!!!!!!!\n"); // child_data->to_be_killed=GRACEFULLY; ci_debug_printf(1, "Jobs in Queue: %d, Free servers: %d, Used Servers: %d, Requests: %d\n", jobs_in_queue, child_data->freeservers, child_data->usedservers, child_data->requests); } ci_thread_mutex_lock(&counters_mtx); haschild = (child_data->freeservers ? 1 : 0); ci_thread_mutex_unlock(&counters_mtx); (child_data->connections)++; //NUM of Requests.... } while (haschild); child_data->idle = 1; ci_proc_mutex_unlock(&accept_mutex); ci_thread_mutex_lock(&counters_mtx); if (child_data->freeservers == 0) { ci_debug_printf(1, "Child %d waiting for a thread to accept more connections ...\n", pid); ci_thread_cond_wait(&free_server_cond, &counters_mtx); } ci_thread_mutex_unlock(&counters_mtx); } }
LDAP *ldap_connection_open(struct ldap_connections_pool *pool) { struct ldap_connection *conn; struct berval ldap_passwd, *servercred; int ret; char *ldap_user; if (ci_thread_mutex_lock(&pool->mutex)!=0) return NULL; #ifdef LDAP_MAX_CONNECTIONS do { #endif if (pool->inactive) { conn = pool->inactive; pool->inactive = pool->inactive->next; conn->next = pool->used; pool->used = conn; conn->hits++; ci_thread_mutex_unlock(&pool->mutex); return conn->ldap; } #ifdef LDAP_MAX_CONNECTIONS if (pool->connections >= pool->max_connections) { /*wait for an ldap connection to be released. The condwait will unlock pool->mutex */ if (ci_thread_cond_wait(&(pool->pool_cond), &(pool->mutex)) != 0) { ci_thread_mutex_unlock(&(pool->mutex)); return NULL; } } } while(pool->connections >= pool->max_connections); #else ci_thread_mutex_unlock(&pool->mutex); #endif conn=malloc(sizeof(struct ldap_connection)); if (!conn) { #ifdef LDAP_MAX_CONNECTIONS ci_thread_mutex_unlock(&pool->mutex); #endif return NULL; } conn->hits = 1; ret = ldap_initialize(&conn->ldap, pool->ldap_uri); if (!conn->ldap) { #ifdef LDAP_MAX_CONNECTIONS ci_thread_mutex_unlock(&pool->mutex); #endif ci_debug_printf(1, "Error allocating memory for ldap connection: %s!\n", ldap_err2string(ret)); free(conn); return NULL; } ldap_set_option(conn->ldap, LDAP_OPT_PROTOCOL_VERSION, &(pool->ldapversion)); if (pool->user[0] != '\0') ldap_user = pool->user; else ldap_user = NULL; if (pool->password[0] != '\0') { ldap_passwd.bv_val = pool->password; ldap_passwd.bv_len = strlen(pool->password); } else { ldap_passwd.bv_val = NULL; ldap_passwd.bv_len = 0; } ret = ldap_sasl_bind_s( conn->ldap, ldap_user, LDAP_SASL_SIMPLE, &ldap_passwd, NULL, NULL, &servercred ); if (ret != LDAP_SUCCESS) { ci_debug_printf(1, "Error bind to ldap server: %s!\n",ldap_err2string(ret)); #ifdef LDAP_MAX_CONNECTIONS ci_thread_mutex_unlock(&pool->mutex); #endif ldap_unbind_ext_s(conn->ldap, NULL, NULL); free(conn); return NULL; } if(servercred) { ber_bvfree(servercred); } #ifdef LDAP_MAX_CONNECTIONS /*we are already locked*/ #else if (ci_thread_mutex_lock(&pool->mutex)!= 0) { ci_debug_printf(1, "Error locking mutex while opening ldap connection!\n"); ldap_unbind_ext_s(conn->ldap, NULL, NULL); free(conn); return NULL; } #endif pool->connections++; conn->next = pool->used; pool->used = conn; ci_thread_mutex_unlock(&pool->mutex); return conn->ldap; }