- fd_set readfds;
- struct ServiceFunctionHook *serviceptr;
- int ssock; /* Descriptor for client socket */
- int highest;
- int m, i;
- int retval = 0;
- struct CitContext *con;
-
-
-
- while (!CtdlThreadCheckStop()) {
- CtdlThreadName("select_on_master");
-
- /* Initialize the fdset. */
- FD_ZERO(&readfds);
- highest = 0;
-
- /* First, add the various master sockets to the fdset. */
- for (serviceptr = ServiceHookTable; serviceptr != NULL;
- serviceptr = serviceptr->next) {
- m = serviceptr->msock;
- FD_SET(m, &readfds);
- if (m > highest) {
- highest = m;
- }
- }
-
- /** We can block indefinately since something will wake us up eventually
- * Even if it is a signal telling us the system is shutting down
- */
- retval =
- CtdlThreadSelect(highest + 1, &readfds, NULL, NULL,
- NULL);
-
- /** Select got an error or we are shutting down so get out */
- if (retval == 0 || CtdlThreadCheckStop()) {
- return NULL;
- }
-
- /** Select says something happened on one of our master sockets so now we handle it */
- for (serviceptr = ServiceHookTable; serviceptr != NULL;
- serviceptr = serviceptr->next) {
- if (FD_ISSET(serviceptr->msock, &readfds)) {
- ssock = accept(serviceptr->msock, NULL, 0);
- if (ssock >= 0) {
- CtdlLogPrintf(CTDL_DEBUG,
- "New client socket %d\n",
- ssock);
- /* The master socket is non-blocking but the client
- * sockets need to be blocking, otherwise certain
- * operations barf on FreeBSD. Not a fatal error.
- */
- if (fcntl(ssock, F_SETFL, 0) < 0) {
- CtdlLogPrintf(CTDL_EMERG,
- "citserver: Can't set socket to blocking: %s\n",
- strerror
- (errno));
- }
- /* New context will be created already
- * set up in the CON_EXECUTING state.
- */
- con = CreateNewContext();
- /* Assign our new socket number to it. */
- con->client_socket = ssock;
- con->h_command_function =
- serviceptr->h_command_function;
- con->h_async_function =
- serviceptr->h_async_function;
- con->ServiceName =
- serviceptr->ServiceName;
- con->h_greeting_function = serviceptr->h_greeting_function;
- /* Determine whether it's a local socket */
- if (serviceptr->sockpath != NULL)
- con->is_local_socket = 1;
-
- /* Set the SO_REUSEADDR socket option */
- i = 1;
- setsockopt(ssock, SOL_SOCKET,
- SO_REUSEADDR, &i,
- sizeof(i));
-
- /** Now we can pass this context to an idle worker thread to get things going
- * What if there are no idle workers?
- * We could create one but what if the thread list is full?
- * Then I guess we need to close the socket a reject the connection.
- */
- /** TODO: If there are no idle threads then this server is overloaded and we should reject the connection
- * This will have the effect of throttling the incomming connections on master sockets
- * a little and slow the process down.
- */
-// if (idle_workers)
- {
- con->state = CON_START;
- citthread_kill(client_select_thread->tid, SIGUSR1);
- citthread_cond_signal(&worker_block);
- }
- // else
- // output try later message
- //start_context(con);
- }
- }
- }
- }
- return NULL;
+ fd_set readfds;
+ struct ServiceFunctionHook *serviceptr;
+ int ssock; /* Descriptor for client socket */
+ int highest;
+ int m, i;
+ int retval = 0;
+ struct timeval tv;
+ struct CitContext *con;
+ const char *old_name;
+
+
+
+ old_name = CtdlThreadName("select_on_master");
+
+ /* Initialize the fdset. */
+ FD_ZERO(&readfds);
+ highest = 0;
+
+ /* First, add the various master sockets to the fdset. */
+ for (serviceptr = ServiceHookTable; serviceptr != NULL; serviceptr = serviceptr->next ) {
+ m = serviceptr->msock;
+ FD_SET(m, &readfds);
+ if (m > highest) {
+ highest = m;
+ }
+ }
+
+ tv.tv_sec = 1; /* wake up every 1 sec if no input */
+ tv.tv_usec = 0;
+ retval = CtdlThreadSelect(highest + 1, &readfds, NULL, NULL, &tv);
+
+ /* Select got an error or we are shutting down so get out */
+ if (retval == 0 || CtdlThreadCheckStop()) {
+ CtdlThreadName(old_name);
+ return;
+ }
+
+ /* Select says something happened on one of our master sockets so now we handle it */
+ for (serviceptr = ServiceHookTable; serviceptr != NULL; serviceptr = serviceptr->next ) {
+ if (FD_ISSET(serviceptr->msock, &readfds)) {
+ ssock = accept(serviceptr->msock, NULL, 0);
+ if (ssock >= 0) {
+ CtdlLogPrintf(CTDL_DEBUG, "New client socket %d\n", ssock);
+ /* The master socket is non-blocking but the client
+ * sockets need to be blocking, otherwise certain
+ * operations barf on FreeBSD. Not a fatal error.
+ */
+ if (fcntl(ssock, F_SETFL, 0) < 0) {
+ CtdlLogPrintf(CTDL_EMERG,
+ "citserver: Can't set socket to blocking: %s\n",
+ strerror(errno));
+ }
+
+ /* New context will be created already
+ * set up in the CON_EXECUTING state.
+ */
+ con = CreateNewContext();
+ CT->Context = con;
+
+ /* Assign our new socket number to it. */
+ con->client_socket = ssock;
+ con->h_command_function = serviceptr->h_command_function;
+ con->h_async_function = serviceptr->h_async_function;
+ con->ServiceName = serviceptr->ServiceName;
+ /* Determine whether it's a local socket */
+ if (serviceptr->sockpath != NULL)
+ con->is_local_socket = 1;
+
+ /* Set the SO_REUSEADDR socket option */
+ i = 1;
+ setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
+
+ become_session(con);
+ begin_session(con);
+ serviceptr->h_greeting_function();
+ become_session(NULL);
+ con->state = CON_IDLE;
+ break;
+ }
+ }
+ }
+
+ CtdlThreadName(old_name);