/* * Callback for freeing a client. */ void client_free(RADCLIENT *client) { if (!client) return; #ifdef WITH_DYNAMIC_CLIENTS if (client->dynamic == 2) { time_t now; if (!deleted_clients) { deleted_clients = fr_fifo_create(1024, (void *) client_free); if (!deleted_clients) return; /* MEMLEAK */ } /* * Mark it as in the fifo, and remember when we * pushed it. */ client->dynamic = 3; client->created = now = time(NULL); /* re-set it */ fr_fifo_push(deleted_clients, client); /* * Peek at the head of the fifo. If it might * still be in use, return. Otherwise, pop it * from the queue and delete it. */ client = fr_fifo_peek(deleted_clients); if ((client->created + 120) >= now) return; client = fr_fifo_pop(deleted_clients); rad_assert(client != NULL); } #endif free(client->longname); free(client->secret); free(client->shortname); free(client->nastype); free(client->login); free(client->password); free(client->server); #ifdef WITH_DYNAMIC_CLIENTS free(client->client_server); #endif free(client); }
/* * Remove a request from the queue. */ static int request_dequeue(REQUEST **prequest) { time_t blocked; static time_t last_complained = 0; RAD_LISTEN_TYPE i, start; REQUEST *request; reap_children(); pthread_mutex_lock(&thread_pool.queue_mutex); #ifdef WITH_STATS #ifdef WITH_ACCOUNTING if (thread_pool.auto_limit_acct) { struct timeval now; gettimeofday(&now, NULL); thread_pool.pps_out.pps = rad_pps(&thread_pool.pps_out.pps_old, &thread_pool.pps_out.pps_now, &thread_pool.pps_out.time_old, &now); thread_pool.pps_out.pps_now++; } #endif #endif /* * Clear old requests from all queues. * * We only do one pass over the queue, in order to * amortize the work across the child threads. Since we * do N checks for one request de-queued, the old * requests will be quickly cleared. */ for (i = 0; i < RAD_LISTEN_MAX; i++) { request = fr_fifo_peek(thread_pool.fifo[i]); if (!request) continue; rad_assert(request->magic == REQUEST_MAGIC); if (request->master_state != REQUEST_STOP_PROCESSING) { continue; } /* * This entry was marked to be stopped. Acknowledge it. */ request = fr_fifo_pop(thread_pool.fifo[i]); rad_assert(request != NULL); request->child_state = REQUEST_DONE; thread_pool.num_queued--; } start = 0; retry: /* * Pop results from the top of the queue */ for (i = start; i < RAD_LISTEN_MAX; i++) { request = fr_fifo_pop(thread_pool.fifo[i]); if (request) { start = i; break; } } if (!request) { pthread_mutex_unlock(&thread_pool.queue_mutex); *prequest = NULL; return 0; } rad_assert(thread_pool.num_queued > 0); thread_pool.num_queued--; *prequest = request; rad_assert(*prequest != NULL); rad_assert(request->magic == REQUEST_MAGIC); request->component = "<core>"; request->module = "<thread>"; /* * If the request has sat in the queue for too long, * kill it. * * The main clean-up code can't delete the request from * the queue, and therefore won't clean it up until we * have acknowledged it as "done". */ if (request->master_state == REQUEST_STOP_PROCESSING) { request->module = "<done>"; request->child_state = REQUEST_DONE; goto retry; } /* * The thread is currently processing a request. */ thread_pool.active_threads++; blocked = time(NULL); if ((blocked - request->timestamp) > 5) { if (last_complained < blocked) { last_complained = blocked; blocked -= request->timestamp; } else { blocked = 0; } } else { blocked = 0; } pthread_mutex_unlock(&thread_pool.queue_mutex); if (blocked) { radlog(L_ERR, "(%u) %s has been waiting in the processing queue for %d seconds. Check that all databases are running properly!", request->number, fr_packet_codes[request->packet->code], (int) blocked); } return 1; }
/* * Remove a request from the queue. */ static int request_dequeue(REQUEST **request, RAD_REQUEST_FUNP *fun) { int blocked; RAD_LISTEN_TYPE i, start; request_queue_t *entry; reap_children(); pthread_mutex_lock(&thread_pool.queue_mutex); /* * Clear old requests from all queues. * * We only do one pass over the queue, in order to * amortize the work across the child threads. Since we * do N checks for one request de-queued, the old * requests will be quickly cleared. */ for (i = 0; i < RAD_LISTEN_MAX; i++) { entry = fr_fifo_peek(thread_pool.fifo[i]); if (!entry || (entry->request->master_state != REQUEST_STOP_PROCESSING)) { continue; } /* * This entry was marked to be stopped. Acknowledge it. */ entry = fr_fifo_pop(thread_pool.fifo[i]); rad_assert(entry != NULL); entry->request->child_state = REQUEST_DONE; thread_pool.num_queued--; free(entry); entry = NULL; } start = 0; retry: /* * Pop results from the top of the queue */ for (i = start; i < RAD_LISTEN_MAX; i++) { entry = fr_fifo_pop(thread_pool.fifo[i]); if (entry) { start = i; break; } } if (!entry) { pthread_mutex_unlock(&thread_pool.queue_mutex); *request = NULL; *fun = NULL; return 0; } rad_assert(thread_pool.num_queued > 0); thread_pool.num_queued--; *request = entry->request; *fun = entry->fun; free(entry); entry = NULL; rad_assert(*request != NULL); rad_assert((*request)->magic == REQUEST_MAGIC); rad_assert(*fun != NULL); (*request)->component = "<core>"; (*request)->module = "<thread>"; /* * If the request has sat in the queue for too long, * kill it. * * The main clean-up code can't delete the request from * the queue, and therefore won't clean it up until we * have acknowledged it as "done". */ if ((*request)->master_state == REQUEST_STOP_PROCESSING) { (*request)->module = "<done>"; (*request)->child_state = REQUEST_DONE; goto retry; } /* * Produce messages for people who have 10 million rows * in a database, without indexes. */ rad_assert(almost_now != 0); blocked = almost_now - (*request)->timestamp; if (blocked < 5) { blocked = 0; } else { static time_t last_complained = 0; if (last_complained != almost_now) { last_complained = almost_now; } else { blocked = 0; } } /* * The thread is currently processing a request. */ thread_pool.active_threads++; pthread_mutex_unlock(&thread_pool.queue_mutex); if (blocked) { radlog(L_ERR, "Request %u has been waiting in the processing queue for %d seconds. Check that all databases are running properly!", (*request)->number, blocked); } return 1; }
/* * Remove a request from the queue. */ static int request_dequeue(REQUEST **prequest, RAD_REQUEST_FUNP *fun) { RAD_LISTEN_TYPE i, start; REQUEST *request = NULL; reap_children(); pthread_mutex_lock(&thread_pool.queue_mutex); /* * Clear old requests from all queues. * * We only do one pass over the queue, in order to * amortize the work across the child threads. Since we * do N checks for one request de-queued, the old * requests will be quickly cleared. */ for (i = 0; i < RAD_LISTEN_MAX; i++) { request = fr_fifo_peek(thread_pool.fifo[i]); if (!request || (request->master_state != REQUEST_STOP_PROCESSING)) { continue; } /* * This entry was marked to be stopped. Acknowledge it. */ request = fr_fifo_pop(thread_pool.fifo[i]); rad_assert(request != NULL); request->child_state = REQUEST_DONE; thread_pool.num_queued--; } start = 0; retry: /* * Pop results from the top of the queue */ for (i = start; i < RAD_LISTEN_MAX; i++) { request = fr_fifo_pop(thread_pool.fifo[i]); if (request) { start = i; break; } } if (!request) { pthread_mutex_unlock(&thread_pool.queue_mutex); *prequest = NULL; *fun = NULL; return 0; } rad_assert(thread_pool.num_queued > 0); thread_pool.num_queued--; *prequest = request; *fun = request->process; rad_assert(request->magic == REQUEST_MAGIC); rad_assert(*fun != NULL); /* * If the request has sat in the queue for too long, * kill it. * * The main clean-up code can't delete the request from * the queue, and therefore won't clean it up until we * have acknowledged it as "done". */ if (request->master_state == REQUEST_STOP_PROCESSING) { request->child_state = REQUEST_DONE; goto retry; } /* * The thread is currently processing a request. */ thread_pool.active_threads++; pthread_mutex_unlock(&thread_pool.queue_mutex); return 1; }