* Initial hack of worker-thread rearchitecture. Right now it is successfully
authorArt Cancro <ajc@citadel.org>
Wed, 27 Oct 1999 04:26:59 +0000 (04:26 +0000)
committerArt Cancro <ajc@citadel.org>
Wed, 27 Oct 1999 04:26:59 +0000 (04:26 +0000)
  dispatching worker threads to active client sockets (and to the master
  socket too, of course).  Removing sessions is currently broken.  There is
  also a problem with worker threads waking up too quickly when a client
  command is entered (race condition?).   More cleanup to follow.

citadel/ChangeLog
citadel/citserver.c
citadel/citserver.h
citadel/server.h
citadel/sysconfig.h
citadel/sysdep.c
citadel/sysdep_decls.h

index 1ab0cbaa1d1c38549ede456876761da5e8366df3..0040631e77e6b7dc4247d567be9818ec269e1a9a 100644 (file)
@@ -1,4 +1,11 @@
 $Log$
+Revision 1.398  1999/10/27 04:26:58  ajc
+* Initial hack of worker-thread rearchitecture.  Right now it is successfully
+  dispatching worker threads to active client sockets (and to the master
+  socket too, of course).  Removing sessions is currently broken.  There is
+  also a problem with worker threads waking up too quickly when a client
+  command is entered (race condition?).   More cleanup to follow.
+
 Revision 1.397  1999/10/26 20:20:29  ajc
 * Removed the auto-reconnect stuff... it was locking the client in an active
   loop more often than it was reconnecting.
@@ -1364,3 +1371,4 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant <bryant@cs.usm.maine.edu>
 
 Fri Jul 10 1998 Art Cancro <ajc@uncnsrd.mt-kisco.ny.us>
        * Initial CVS import 
+
index 738e866950ed626d114a0d9edd27b78c7a334e5d..cd791e3583587ba67191f4aca0f9e7ca6cad04c3 100644 (file)
@@ -122,9 +122,9 @@ void deallocate_user_data(struct CitContext *con)
  * All NON-system-dependent stuff is done in this function.
  * System-dependent session/thread cleanup is in cleanup() in sysdep.c
  */
-void cleanup_stuff(void *arg)
+void cleanup(int exit_code)
 {
-       lprintf(9, "cleanup_stuff() called\n");
+       lprintf(9, "cleanup(%d) called\n", exit_code);
 
        lprintf(7, "Calling logout(%d)\n", CC->cs_pid);
        logout(CC);
@@ -141,13 +141,8 @@ void cleanup_stuff(void *arg)
        /* Deallocate any user-data attached to this session */
        deallocate_user_data(CC);
 
-       /* Tell the housekeeping thread to remove the session and context.
-        * This can't be done inline because the context data gets destroyed
-        * halfway through, and the context being destroyed can't be the one
-        * doing the work.
-        */
-       lprintf(7, "Calling RemoveContext(%d)\n", CC->cs_pid);
-       RemoveContext(CC);
+       /* And flag the context as in need of being killed */
+       CC->state = CON_DYING;
        }
 
 
@@ -801,460 +796,464 @@ void cmd_scdn(char *argbuf)
 
 
 /*
- * main context loop
+ * 
  */
-void *context_loop(struct CitContext *con)
+void begin_session(struct CitContext *con)
 {
-       char cmdbuf[256];
        int num_sessions, len;
        struct sockaddr_in sin;
 
-       /*
-        * Wedge our way into the context table.
-        */
-       InitMyContext(con);
-
        /* 
         * Initialize some variables specific to our context.
         */
-       CC->logged_in = 0;
-       CC->internal_pgm = 0;
-       CC->download_fp = NULL;
-       CC->upload_fp = NULL;
-       CC->cs_pid = con->client_socket;        /* not necessarily portable */
-       CC->FirstExpressMessage = NULL;
-       time(&CC->lastcmd);
-       time(&CC->lastidle);
-       strcpy(CC->lastcmdname, "    ");
-       strcpy(CC->cs_clientname, "(unknown)");
-       strcpy(CC->curr_user,"(not logged in)");
-       strcpy(CC->net_node,"");
-       snprintf(CC->temp, sizeof CC->temp, tmpnam(NULL));
-       safestrncpy(CC->cs_host, config.c_fqdn, sizeof CC->cs_host);
-       CC->cs_host[sizeof CC->cs_host - 1] = 0;
+       con->logged_in = 0;
+       con->internal_pgm = 0;
+       con->download_fp = NULL;
+       con->upload_fp = NULL;
+       con->cs_pid = con->client_socket;       /* not necessarily portable */
+       con->FirstExpressMessage = NULL;
+       time(&con->lastcmd);
+       time(&con->lastidle);
+       strcpy(con->lastcmdname, "    ");
+       strcpy(con->cs_clientname, "(unknown)");
+       strcpy(con->curr_user,"(not logged in)");
+       strcpy(con->net_node,"");
+       snprintf(con->temp, sizeof con->temp, tmpnam(NULL));
+       safestrncpy(con->cs_host, config.c_fqdn, sizeof con->cs_host);
+       con->cs_host[sizeof con->cs_host - 1] = 0;
        len = sizeof sin;
-       if (!getpeername(CC->client_socket, (struct sockaddr *) &sin, &len))
-               locate_host(CC->cs_host, &sin.sin_addr);
-       CC->cs_flags = 0;
-       CC->upload_type = UPL_FILE;
-       CC->dl_is_net = 0;
-       CC->FirstSessData = NULL;
+       if (!getpeername(con->client_socket, (struct sockaddr *) &sin, &len))
+               locate_host(con->cs_host, &sin.sin_addr);
+       con->cs_flags = 0;
+       con->upload_type = UPL_FILE;
+       con->dl_is_net = 0;
+       con->FirstSessData = NULL;
 
        num_sessions = session_count();
-       CC->nologin = 0;
+       con->nologin = 0;
        if ((config.c_maxsessions > 0)&&(num_sessions > config.c_maxsessions))
-               CC->nologin = 1;
+               con->nologin = 1;
 
-       if (CC->nologin==1) {
-          cprintf("%d %s: Too many users are already online (maximum is %d)\n",
-               ERROR+MAX_SESSIONS_EXCEEDED,
-               config.c_nodename,config.c_maxsessions);
+       if (con->nologin==1) {
+               cprintf("%d %s: Too many users are already online "
+                       "(maximum is %d)\n",
+                       ERROR+MAX_SESSIONS_EXCEEDED,
+                       config.c_nodename, config.c_maxsessions);
                }
        else {
-          cprintf("%d %s Citadel/UX server ready.\n",OK,config.c_nodename);
+               cprintf("%d %s Citadel/UX server ready.\n",
+                       OK, config.c_nodename);
                }
 
-       lprintf(3, "citserver[%3d]: started.\n", CC->cs_pid);
+       lprintf(3, "citserver[%3d]: started.\n", con->cs_pid);
 
        /* Run any session startup routines registered by loadable modules */
        PerformSessionHooks(EVT_START);
 
        rec_log(CL_CONNECT, "");
+}
+
+
+
 
-       do {
-               time(&CC->lastcmd);
-               memset(cmdbuf, 0, sizeof cmdbuf); /* Clear it, just in case */
-               if (client_gets(cmdbuf) < 1) cleanup(EXIT_NULL);
-               lprintf(5, "citserver[%3d]: %s\n", CC->cs_pid, cmdbuf);
-
-               /*
-                * Let other clients see the last command we executed, and
-                * update the idle time, but not NOOP, PEXP, or GEXP.
-                */
-               if ( (strncasecmp(cmdbuf, "NOOP", 4))
-                  && (strncasecmp(cmdbuf, "PEXP", 4))
-                  && (strncasecmp(cmdbuf, "GEXP", 4)) ) {
-                       strcpy(CC->lastcmdname, "    ");
-                       safestrncpy(CC->lastcmdname, cmdbuf, 
-                               sizeof(CC->lastcmdname) );
-                       time(&CC->lastidle);
-                       }
-                       
-               if ((strncasecmp(cmdbuf, "ENT0", 4)) && (strncasecmp(cmdbuf, "MESG", 4)) && (strncasecmp(cmdbuf, "MSGS", 4)))
-               {
-                  CC->cs_flags &= ~CS_POSTING;
-               }
-                  
 /*
  * This loop recognizes all server commands.
  */
+void do_command_loop(void) {
+       char cmdbuf[256];
 
-               if (!strncasecmp(cmdbuf,"NOOP",4)) {
-                       cprintf("%d%cok\n",OK,check_express());
-                       }
+       lprintf(9, "Hi, I'm do_command_loop() and I have client socket %d\n",
+               CC->client_socket);
 
-               else if (!strncasecmp(cmdbuf,"QUIT",4)) {
-                       cprintf("%d Goodbye.\n",OK);
-                       }
+       time(&CC->lastcmd);
+       memset(cmdbuf, 0, sizeof cmdbuf); /* Clear it, just in case */
+       if (client_gets(cmdbuf) < 1) {
+               lprintf(3, "Socket is broken, I think.\n");
+               cleanup(EXIT_NULL);
+       }
+       lprintf(5, "citserver[%3d]: %s\n", CC->cs_pid, cmdbuf);
 
-               else if (!strncasecmp(cmdbuf,"LOUT",4)) {
-                       if (CC->logged_in) logout(CC);
-                       cprintf("%d logged out.\n",OK);
-                       }
+       /*
+        * Let other clients see the last command we executed, and
+        * update the idle time, but not NOOP, PEXP, or GEXP.
+        */
+       if ( (strncasecmp(cmdbuf, "NOOP", 4))
+          && (strncasecmp(cmdbuf, "PEXP", 4))
+          && (strncasecmp(cmdbuf, "GEXP", 4)) ) {
+               strcpy(CC->lastcmdname, "    ");
+               safestrncpy(CC->lastcmdname, cmdbuf, 
+                       sizeof(CC->lastcmdname) );
+               time(&CC->lastidle);
+               }
+               
+       if ((strncasecmp(cmdbuf, "ENT0", 4))
+          && (strncasecmp(cmdbuf, "MESG", 4))
+          && (strncasecmp(cmdbuf, "MSGS", 4)))
+       {
+          CC->cs_flags &= ~CS_POSTING;
+       }
+                  
+       if (!strncasecmp(cmdbuf,"NOOP",4)) {
+               cprintf("%d%cok\n",OK,check_express());
+               }
 
-               else if (!strncasecmp(cmdbuf,"USER",4)) {
-                       cmd_user(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"QUIT",4)) {
+               cprintf("%d Goodbye.\n",OK);
+               }
 
-               else if (!strncasecmp(cmdbuf,"PASS",4)) {
-                       cmd_pass(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"LOUT",4)) {
+               if (CC->logged_in) logout(CC);
+               cprintf("%d logged out.\n",OK);
+               }
 
-               else if (!strncasecmp(cmdbuf,"NEWU",4)) {
-                       cmd_newu(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"USER",4)) {
+               cmd_user(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"SETP",4)) {
-                       cmd_setp(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"PASS",4)) {
+               cmd_pass(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"LRMS",4)) {
-                       cmd_lrms(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"NEWU",4)) {
+               cmd_newu(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"LKRA",4)) {
-                       cmd_lkra(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"SETP",4)) {
+               cmd_setp(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"LKRN",4)) {
-                       cmd_lkrn(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"LRMS",4)) {
+               cmd_lrms(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"LKRO",4)) {
-                       cmd_lkro(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"LKRA",4)) {
+               cmd_lkra(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"LZRM",4)) {
-                       cmd_lzrm(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"LKRN",4)) {
+               cmd_lkrn(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"GETU",4)) {
-                       cmd_getu();
-                       }
+       else if (!strncasecmp(cmdbuf,"LKRO",4)) {
+               cmd_lkro(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"SETU",4)) {
-                       cmd_setu(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"LZRM",4)) {
+               cmd_lzrm(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"GOTO",4)) {
-                       cmd_goto(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"GETU",4)) {
+               cmd_getu();
+               }
 
-               else if (!strncasecmp(cmdbuf,"MSGS",4)) {
-                       cmd_msgs(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"SETU",4)) {
+               cmd_setu(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"WHOK",4)) {
-                       cmd_whok();
-                       }
+       else if (!strncasecmp(cmdbuf,"GOTO",4)) {
+               cmd_goto(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"RDIR",4)) {
-                       cmd_rdir();
-                       }
+       else if (!strncasecmp(cmdbuf,"MSGS",4)) {
+               cmd_msgs(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"MSG0",4)) {
-                       cmd_msg0(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"WHOK",4)) {
+               cmd_whok();
+               }
 
-               else if (!strncasecmp(cmdbuf,"MSG2",4)) {
-                       cmd_msg2(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"RDIR",4)) {
+               cmd_rdir();
+               }
 
-               else if (!strncasecmp(cmdbuf,"MSG3",4)) {
-                       cmd_msg3(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"MSG0",4)) {
+               cmd_msg0(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"MSG4",4)) {
-                       cmd_msg4(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"MSG2",4)) {
+               cmd_msg2(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"OPNA",4)) {
-                       cmd_opna(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"MSG3",4)) {
+               cmd_msg3(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"INFO",4)) {
-                       cmd_info();
-                       }
+       else if (!strncasecmp(cmdbuf,"MSG4",4)) {
+               cmd_msg4(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"SLRP",4)) {
-                       cmd_slrp(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"OPNA",4)) {
+               cmd_opna(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"INVT",4)) {
-                       cmd_invt_kick(&cmdbuf[5],1);
-                       }
+       else if (!strncasecmp(cmdbuf,"INFO",4)) {
+               cmd_info();
+               }
 
-               else if (!strncasecmp(cmdbuf,"KICK",4)) {
-                       cmd_invt_kick(&cmdbuf[5],0);
-                       }
+       else if (!strncasecmp(cmdbuf,"SLRP",4)) {
+               cmd_slrp(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"GETR",4)) {
-                       cmd_getr();
-                       }
+       else if (!strncasecmp(cmdbuf,"INVT",4)) {
+               cmd_invt_kick(&cmdbuf[5],1);
+               }
 
-               else if (!strncasecmp(cmdbuf,"SETR",4)) {
-                       cmd_setr(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"KICK",4)) {
+               cmd_invt_kick(&cmdbuf[5],0);
+               }
 
-               else if (!strncasecmp(cmdbuf,"GETA",4)) {
-                       cmd_geta();
-                       }
+       else if (!strncasecmp(cmdbuf,"GETR",4)) {
+               cmd_getr();
+               }
 
-               else if (!strncasecmp(cmdbuf,"SETA",4)) {
-                       cmd_seta(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"SETR",4)) {
+               cmd_setr(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"ENT0",4)) {
-                       cmd_ent0(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"GETA",4)) {
+               cmd_geta();
+               }
 
-               else if (!strncasecmp(cmdbuf,"ENT3",4)) {
-                       cmd_ent3(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"SETA",4)) {
+               cmd_seta(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"RINF",4)) {
-                       cmd_rinf();
-                       }
+       else if (!strncasecmp(cmdbuf,"ENT0",4)) {
+               cmd_ent0(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"DELE",4)) {
-                       cmd_dele(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"ENT3",4)) {
+               cmd_ent3(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"KILL",4)) {
-                       cmd_kill(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"RINF",4)) {
+               cmd_rinf();
+               }
 
-               else if (!strncasecmp(cmdbuf,"CRE8",4)) {
-                       cmd_cre8(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"DELE",4)) {
+               cmd_dele(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"MOVE",4)) {
-                       cmd_move(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"KILL",4)) {
+               cmd_kill(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"FORG",4)) {
-                       cmd_forg();
-                       }
+       else if (!strncasecmp(cmdbuf,"CRE8",4)) {
+               cmd_cre8(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"MESG",4)) {
-                       cmd_mesg(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"MOVE",4)) {
+               cmd_move(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"EMSG",4)) {
-                       cmd_emsg(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"FORG",4)) {
+               cmd_forg();
+               }
 
-               else if (!strncasecmp(cmdbuf,"GNUR",4)) {
-                       cmd_gnur();
-                       }
+       else if (!strncasecmp(cmdbuf,"MESG",4)) {
+               cmd_mesg(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"VALI",4)) {
-                       cmd_vali(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"EMSG",4)) {
+               cmd_emsg(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"EINF",4)) {
-                       cmd_einf(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"GNUR",4)) {
+               cmd_gnur();
+               }
 
-               else if (!strncasecmp(cmdbuf,"LIST",4)) {
-                       cmd_list();
-                       }
+       else if (!strncasecmp(cmdbuf,"VALI",4)) {
+               cmd_vali(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"CHEK",4)) {
-                       cmd_chek();
-                       }
+       else if (!strncasecmp(cmdbuf,"EINF",4)) {
+               cmd_einf(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"DELF",4)) {
-                       cmd_delf(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"LIST",4)) {
+               cmd_list();
+               }
 
-               else if (!strncasecmp(cmdbuf,"MOVF",4)) {
-                       cmd_movf(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"CHEK",4)) {
+               cmd_chek();
+               }
 
-               else if (!strncasecmp(cmdbuf,"NETF",4)) {
-                       cmd_netf(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"DELF",4)) {
+               cmd_delf(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"RWHO",4)) {
-                       cmd_rwho();
-                       }
+       else if (!strncasecmp(cmdbuf,"MOVF",4)) {
+               cmd_movf(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"OPEN",4)) {
-                       cmd_open(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"NETF",4)) {
+               cmd_netf(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"CLOS",4)) {
-                       cmd_clos();
-                       }
+       else if (!strncasecmp(cmdbuf,"RWHO",4)) {
+               cmd_rwho();
+               }
 
-               else if (!strncasecmp(cmdbuf,"UOPN",4)) {
-                       cmd_uopn(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"OPEN",4)) {
+               cmd_open(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"UCLS",4)) {
-                       cmd_ucls(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"CLOS",4)) {
+               cmd_clos();
+               }
 
-               else if (!strncasecmp(cmdbuf,"READ",4)) {
-                       cmd_read(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"UOPN",4)) {
+               cmd_uopn(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"WRIT",4)) {
-                       cmd_writ(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"UCLS",4)) {
+               cmd_ucls(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"QUSR",4)) {
-                       cmd_qusr(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"READ",4)) {
+               cmd_read(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"ECHO",4)) {
-                       cmd_echo(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"WRIT",4)) {
+               cmd_writ(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"OIMG",4)) {
-                       cmd_oimg(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"QUSR",4)) {
+               cmd_qusr(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"MORE",4)) {
-                       cmd_more();
-                       }
+       else if (!strncasecmp(cmdbuf,"ECHO",4)) {
+               cmd_echo(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"NETP",4)) {
-                       cmd_netp(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"OIMG",4)) {
+               cmd_oimg(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"NDOP",4)) {
-                       cmd_ndop(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"MORE",4)) {
+               cmd_more();
+               }
 
-               else if (!strncasecmp(cmdbuf,"NUOP",4)) {
-                       cmd_nuop(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"NETP",4)) {
+               cmd_netp(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"LFLR",4)) {
-                       cmd_lflr();
-                       }
+       else if (!strncasecmp(cmdbuf,"NDOP",4)) {
+               cmd_ndop(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"CFLR",4)) {
-                       cmd_cflr(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"NUOP",4)) {
+               cmd_nuop(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"KFLR",4)) {
-                       cmd_kflr(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"LFLR",4)) {
+               cmd_lflr();
+               }
 
-               else if (!strncasecmp(cmdbuf,"EFLR",4)) {
-                       cmd_eflr(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"CFLR",4)) {
+               cmd_cflr(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"IDEN",4)) {
-                       cmd_iden(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"KFLR",4)) {
+               cmd_kflr(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"IPGM",4)) {
-                       cmd_ipgm(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"EFLR",4)) {
+               cmd_eflr(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"EBIO",4)) {
-                       cmd_ebio();
-                       }
+       else if (!strncasecmp(cmdbuf,"IDEN",4)) {
+               cmd_iden(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"RBIO",4)) {
-                       cmd_rbio(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"IPGM",4)) {
+               cmd_ipgm(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"LBIO",4)) {
-                       cmd_lbio();
-                       }
+       else if (!strncasecmp(cmdbuf,"EBIO",4)) {
+               cmd_ebio();
+               }
 
-               else if (!strncasecmp(cmdbuf,"STEL",4)) {
-                       cmd_stel(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"RBIO",4)) {
+               cmd_rbio(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"TERM",4)) {
-                       cmd_term(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"LBIO",4)) {
+               cmd_lbio();
+               }
 
-               else if (!strncasecmp(cmdbuf,"DOWN",4)) {
-                       cmd_down();
-                       }
+       else if (!strncasecmp(cmdbuf,"STEL",4)) {
+               cmd_stel(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf,"SCDN",4)) {
-                       cmd_scdn(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"TERM",4)) {
+               cmd_term(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf, "NSET", 4)) {
-                       cmd_nset(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"DOWN",4)) {
+               cmd_down();
+               }
 
-               else if (!strncasecmp(cmdbuf, "UIMG", 4)) {
-                       cmd_uimg(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf,"SCDN",4)) {
+               cmd_scdn(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf, "UCHG", 4)) {
-                       cmd_uchg(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf, "NSET", 4)) {
+               cmd_nset(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf, "TIME", 4)) {
-                       cmd_time();
-                       }
+       else if (!strncasecmp(cmdbuf, "UIMG", 4)) {
+               cmd_uimg(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf, "HCHG", 4)) {
-                       cmd_hchg(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf, "UCHG", 4)) {
+               cmd_uchg(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf, "RCHG", 4)) {
-                       cmd_rchg(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf, "TIME", 4)) {
+               cmd_time();
+               }
 
-               else if (!strncasecmp(cmdbuf, "AGUP", 4)) {
-                       cmd_agup(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf, "HCHG", 4)) {
+               cmd_hchg(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf, "ASUP", 4)) {
-                       cmd_asup(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf, "RCHG", 4)) {
+               cmd_rchg(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf, "GPEX", 4)) {
-                       cmd_gpex(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf, "AGUP", 4)) {
+               cmd_agup(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf, "SPEX", 4)) {
-                       cmd_spex(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf, "ASUP", 4)) {
+               cmd_asup(&cmdbuf[5]);
+               }
 
-               else if (!strncasecmp(cmdbuf, "CONF", 4)) {
-                       cmd_conf(&cmdbuf[5]);
-                       }
+       else if (!strncasecmp(cmdbuf, "GPEX", 4)) {
+               cmd_gpex(&cmdbuf[5]);
+               }
 
-#ifdef DEBUG_MEMORY_LEAKS
-               else if (!strncasecmp(cmdbuf, "LEAK", 4)) {
-                       dump_tracked();
-                       }
-#endif
+       else if (!strncasecmp(cmdbuf, "SPEX", 4)) {
+               cmd_spex(&cmdbuf[5]);
+               }
 
-               else if (!DLoader_Exec_Cmd(cmdbuf))
-                       {
-                          cprintf("%d Unrecognized or unsupported command.\n",
-                                   ERROR);
-                       }
+       else if (!strncasecmp(cmdbuf, "CONF", 4)) {
+               cmd_conf(&cmdbuf[5]);
+               }
 
-               /* Run any after-each-command outines registered by modules */
-               PerformSessionHooks(EVT_CMD);
+#ifdef DEBUG_MEMORY_LEAKS
+       else if (!strncasecmp(cmdbuf, "LEAK", 4)) {
+               dump_tracked();
+               }
+#endif
 
-               } while(strncasecmp(cmdbuf, "QUIT", 4));
+       else if (!DLoader_Exec_Cmd(cmdbuf))
+               {
+                  cprintf("%d Unrecognized or unsupported command.\n",
+                           ERROR);
+               }
 
-       cleanup(EXIT_NORMAL);
-       return(NULL);
-       }
+       /* Run any after-each-command outines registered by modules */
+       PerformSessionHooks(EVT_CMD);
+}
index 53a7801f2da9d887755c3dc9db846beb8f544172..45ac8d519ca82473b3e5f66063007a7f3915de5c 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$ */
 void master_startup (void);
 void master_cleanup (void);
-void cleanup_stuff (void *arg);
+void cleanup (int);
 void set_wtmpsupp (char *newtext);
 void set_wtmpsupp_to_current_room(void);
 void cmd_info (void);
@@ -22,12 +22,13 @@ void cmd_ipgm (char *argbuf);
 void cmd_down (void);
 void cmd_scdn (char *argbuf);
 void cmd_extn (char *argbuf);
-void *context_loop (struct CitContext *con);
 void deallocate_user_data(struct CitContext *con);
 void *CtdlGetUserData(unsigned long requested_sym);
 void CtdlAllocUserData(unsigned long requested_sym, size_t num_bytes);
 int CtdlGetDynamicSymbol(void);
 void enter_housekeeping_cmd(char *);
+void do_command_loop(void);
+void begin_session(struct CitContext *con);
 void GenerateRoomDisplay(char *real_room,
                         struct CitContext *viewed,
                         struct CitContext *viewer);
index 2f977a9d9c0dc230e01912114c95ce110da27e47..b693c275dd87d478aac870043574e6f876ab4fd9 100644 (file)
@@ -56,6 +56,8 @@ struct CitContext {
        struct usersupp usersupp;       /* Database record buffers */
        struct quickroom quickroom;
 
+       int state;              /* thread state (see CON_ values below) */
+
        char curr_user[32];     /* name of current user */
        int logged_in;          /* logged in */
        int internal_pgm;       /* authenticated as internal program */
@@ -63,8 +65,6 @@ struct CitContext {
        int nologin;            /* not allowed to log in */
 
        char net_node[32];
-       THREAD mythread;
-       int n_crit;             /* number of critical sections open */
        int client_socket;
        int cs_pid;             /* session ID */
        time_t cs_lastupdt;     /* time of last update */
@@ -103,6 +103,14 @@ struct CitContext {
 
 typedef struct CitContext t_context;
 
+/* Values for CitContext.state */
+enum {
+       CON_IDLE,               /* This context is doing nothing */
+       CON_EXECUTING,          /* This context is bound to a thread */
+       CON_DYING               /* This context is being terminated */
+};
+
+
 #define CS_STEALTH     1       /* stealth mode */
 #define CS_CHAT                2       /* chat mode */
 #define CS_POSTING     4       /* Posting */
@@ -153,6 +161,7 @@ enum {
        S_DATABASE,
        S_NETDB,
        S_SUPPMSGMAIN,
+       S_I_WANNA_SELECT,
        MAX_SEMAPHORES
 };
 
index 200fc27ea71cfb1bfbd2dd98e6aa1ac15921123a..bda55ed289eed908f74e23c803eb1627ff9c75d8 100644 (file)
  */
 #define HOUSEKEEPING_WAKEUP    60
 
+/*
+ * We'll almost certainly want to do this more elegantly.  For now we are
+ * creating a fixed-size pool of worker threads.
+ */
+#define NUM_WORKER_THREADS     15
+
 
 /*** STRUCTURE SIZE VARIABLES ***/
 
index ea92e4772fffe3f99f353bf6410a86b740779862..0f004f172645af4817b4d81d3ea38313f56a6b81 100644 (file)
@@ -70,7 +70,7 @@ int msock;                                    /* master listening socket */
 int verbosity = 9;                             /* Logging level */
 
 struct CitContext masterCC;
-
+int rescan[2];                                 /* The Rescan Pipe */
 
 /*
  * lprintf()  ...   Write logging information
@@ -244,72 +244,16 @@ void init_sysdep(void) {
  */
 void begin_critical_section(int which_one)
 {
-#ifdef HAVE_PTHREAD_CANCEL
-       int oldval;
-#else
-       sigset_t set;
-#endif
-
-       /* lprintf(8, "begin_critical_section(%d)\n", which_one); */
-
-       if (!pthread_equal(pthread_self(), main_thread_id)) {
-               /* Keep a count of how many critical sections this thread has
-                * open, so that end_critical_section() doesn't enable
-                * cancellation prematurely. */
-               if (CC != NULL) CC->n_crit++;
-#ifdef HAVE_PTHREAD_CANCEL
-               /* Don't get interrupted during the critical section */
-               pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldval);
-#else
-               /* We're faking cancellation with signals. Block SIGUSR1 while
-                * we're in the critical section. */
-               sigemptyset(&set);
-               sigaddset(&set, SIGUSR1);
-               pthread_sigmask(SIG_BLOCK, &set, NULL);
-#endif
-               }
-
-       /* Obtain a semaphore */
        pthread_mutex_lock(&Critters[which_one]);
-
-       }
+}
 
 /*
  * Release a semaphore lock to end a critical section.
  */
 void end_critical_section(int which_one)
 {
-#ifdef HAVE_PTHREAD_CANCEL
-       int oldval;
-#else
-       sigset_t set;
-#endif
-
-       /* lprintf(8, "  end_critical_section(%d)\n", which_one); */
-
-       /* Let go of the semaphore */
        pthread_mutex_unlock(&Critters[which_one]);
-
-       if (!pthread_equal(pthread_self(), main_thread_id))
-       if (CC != NULL)
-       if (!--CC->n_crit) {
-#ifdef HAVE_PTHREAD_CANCEL
-               /* If a cancel was sent during the critical section, do it now.
-                * Then re-enable thread cancellation.
-                */
-               pthread_testcancel();
-               pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldval);
-               pthread_testcancel();
-#else
-               /* We're faking it. Unblock SIGUSR1; signals sent during the
-                * critical section should now be able to kill us. */
-               sigemptyset(&set);
-               sigaddset(&set, SIGUSR1);
-               pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-#endif
-               }
-
-       }
+}
 
 
 
@@ -359,26 +303,6 @@ int ig_tcp_server(int port_number, int queue_len)
        }
 
 
-/*
- * Return a pointer to a thread's own CitContext structure (old)
- * NOTE: this version of MyContext() is commented out because it is no longer
- * in use.  It was written before I discovered TSD keys.  This
- * version pounds through the context list until it finds the one matching
- * the currently running thread.  It remains here, commented out, in case it
- * is needed for future ports to threading libraries which have the equivalent
- * of pthread_self() but not pthread_key_create() and its ilk.
- *
- * struct CitContext *MyContext() {
- *     struct CitContext *ptr;
- *     THREAD me;
- *
- *     me = pthread_self();
- *     for (ptr=ContextList; ptr!=NULL; ptr=ptr->next) {
- *             if (ptr->mythread == me) return(ptr);
- *             }
- *     return(NULL);
- *     }
- */
 
 /*
  * Return a pointer to a thread's own CitContext structure (new)
@@ -400,10 +324,16 @@ struct CitContext *CreateNewContext(void) {
        me = (struct CitContext *) mallok(sizeof(struct CitContext));
        if (me == NULL) {
                lprintf(1, "citserver: can't allocate memory!!\n");
-               pthread_exit(NULL);
+               return NULL;
                }
        memset(me, 0, sizeof(struct CitContext));
 
+       /* The new context will be created already in the CON_EXECUTING state
+        * in order to prevent another thread from grabbing it while it's
+        * being set up.
+        */
+       me->state = CON_EXECUTING;
+
        begin_critical_section(S_SESSION_TABLE);
        me->next = ContextList;
        ContextList = me;
@@ -411,26 +341,6 @@ struct CitContext *CreateNewContext(void) {
        return(me);
        }
 
-/*
- * Add a thread's thread ID to the context
- */
-void InitMyContext(struct CitContext *con)
-{
-#ifdef HAVE_PTHREAD_CANCEL
-       int oldval;
-#endif
-
-       con->mythread = pthread_self();
-#ifdef HAVE_PTHREAD_CANCEL
-       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldval);
-       pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldval);
-#endif
-       if (pthread_setspecific(MyConKey, (void *)con) != 0) {
-               lprintf(1, "ERROR!  pthread_setspecific() failed: %s\n",
-                       strerror(errno));
-               }
-       }
-
 /*
  * Remove a context from the context list.
  */
@@ -555,11 +465,12 @@ int client_read_to(char *buf, int bytes, int timeout)
        while(len<bytes) {
                FD_ZERO(&rfds);
                FD_SET(CC->client_socket, &rfds);
-               tv.tv_sec = timeout;
+               tv.tv_sec = 1;
                tv.tv_usec = 0;
 
                retval = select( (CC->client_socket)+1, 
                                        &rfds, NULL, NULL, &tv);
+
                if (FD_ISSET(CC->client_socket, &rfds) == 0) {
                        return(0);
                        }
@@ -627,60 +538,23 @@ void sysdep_master_cleanup(void) {
        close(msock);
        }
 
-/*
- * Cleanup routine to be called when one thread is shutting down.
- */
-void cleanup(int exit_code)
-{
-       /* Terminate the thread.
-        * Its cleanup handler will call cleanup_stuff()
-        */
-       lprintf(7, "Calling pthread_exit()\n");
-       pthread_exit(NULL);
-       }
 
 /*
  * Terminate another session.
  */
 void kill_session(int session_to_kill) {
        struct CitContext *ptr;
-       THREAD killme = 0;
 
        begin_critical_section(S_SESSION_TABLE);
        for (ptr = ContextList; ptr != NULL; ptr = ptr->next) {
                if (ptr->cs_pid == session_to_kill) {
-                       killme = ptr->mythread;
+                       ptr->state = CON_DYING;
                        }
                }
        end_critical_section(S_SESSION_TABLE);
-
-       if (killme != 0) {
-#ifdef HAVE_PTHREAD_CANCEL
-               pthread_cancel(killme);
-#else
-               pthread_kill(killme, SIGUSR1);
-#ifdef __FreeBSD__
-               /* there's a very stupid bug in the user threads package on
-                  FreeBSD 3.1 which prevents a signal from being properly
-                  dispatched to a thread that's in a blocking syscall. the
-                  first signal interrupts the syscall, the second one actually
-                  gets delivered. */
-               pthread_kill(killme, SIGUSR1);
-#endif
-#endif
-               }
        }
 
 
-/*
- * The system-dependent wrapper around the main context loop.
- */
-void *sd_context_loop(struct CitContext *con) {
-       pthread_cleanup_push(*cleanup_stuff, NULL);
-       context_loop(con);
-       pthread_cleanup_pop(0);
-       return NULL;
-       }
 
 
 /*
@@ -798,17 +672,10 @@ int convert_login(char NameToConvert[]) {
  */
 int main(int argc, char **argv)
 {
-       struct sockaddr_in fsin;        /* Data for master socket */
-       int alen;                       /* Data for master socket */
-       int ssock;                      /* Descriptor for master socket */
-       THREAD SessThread;              /* Thread descriptor */
        THREAD HousekeepingThread;      /* Thread descriptor */
         pthread_attr_t attr;           /* Thread attributes */
-       struct CitContext *con;         /* Temporary context pointer */
        char tracefile[128];            /* Name of file to log traces to */
        int a, i;                       /* General-purpose variables */
-       fd_set readfds;
-       struct timeval tv;
        struct passwd *pw;
        int drop_root_perms = 1;
        char *moddir;
@@ -934,55 +801,203 @@ int main(int argc, char **argv)
                        strerror(errno));
        }
 
-       /* 
-        * Endless loop.  Listen on the master socket.  When a connection
-        * comes in, create a socket, a context, and a thread.
-        */     
+
+       /*
+        * The rescan pipe exists so that worker threads can be woken up and
+        * told to re-scan the context list for fd's to listen on.  This is
+        * necessary, for example, when a context is about to go idle and needs
+        * to get back on that list.
+        */
+       if (pipe(rescan)) {
+               lprintf(1, "Can't create rescan pipe!\n");
+               exit(errno);
+       }
+
+       /*
+        * Now create a bunch of worker threads.
+        */
+       for (i=0; i<(NUM_WORKER_THREADS-1); ++i) {
+               pthread_attr_init(&attr);
+                       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+               if (pthread_create(&HousekeepingThread, &attr,
+                  (void* (*)(void*)) worker_thread, NULL) != 0) {
+                       lprintf(1, "Can't create worker thead: %s\n",
+                       strerror(errno));
+               }
+       }
+
+       /* Now this thread can become a worker as well. */
+       worker_thread();
+
+       return(0);
+}
+
+
+
+
+
+
+
+/* 
+ * This loop just keeps going and going and going...
+ */    
+void worker_thread(void) {
+       int i;
+       char junk;
+       int numselect = 0;
+       int highest;
+       struct CitContext *ptr;
+       struct CitContext *bind_me = NULL;
+       fd_set readfds;
+       int retval;
+       struct CitContext *con= NULL;   /* Temporary context pointer */
+       struct sockaddr_in fsin;        /* Data for master socket */
+       int alen;                       /* Data for master socket */
+       int ssock;                      /* Descriptor for master socket */
+
        while (!time_to_die) {
-               /* we need to check if a signal has been delivered. because
-                * syscalls may be restartable across signals, we call
-                * select with a timeout of 1 second and repeatedly check for
-                * time_to_die... */
+
+               /* 
+                * In a stupid environment, we would have all idle threads
+                * calling select() and then they'd all wake up at once.  We
+                * solve this problem by putting the select() in a critical
+                * section, so only one thread has the opportunity to wake
+                * up.  If we wake up on the master socket, create a new
+                * session context; otherwise, just bind the thread to the
+                * context we want and go on our merry way.
+                */
+
+               begin_critical_section(S_I_WANNA_SELECT);
+               lprintf(9, "Worker thread %2d woke up\n", getpid());
+
+SETUP_FD:
                FD_ZERO(&readfds);
                FD_SET(msock, &readfds);
-               tv.tv_sec = 1;
-               tv.tv_usec = 0;
-               if (select(msock + 1, &readfds, NULL, NULL, &tv) <= 0)
-                       continue;
-               alen = sizeof fsin;
-               ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
-               if (ssock < 0) {
-                       lprintf(2, "citserver: accept() failed: %s\n",
-                               strerror(errno));
+               highest = msock;
+               FD_SET(rescan[0], &readfds);
+               if (rescan[0] > highest) highest = rescan[0];
+               numselect = 2;
+
+               begin_critical_section(S_SESSION_TABLE);
+               for (ptr = ContextList; ptr != NULL; ptr = ptr->next) {
+                       if (ptr->state == CON_IDLE) {
+                               FD_SET(ptr->client_socket, &readfds);
+                               if (ptr->client_socket > highest)
+                                       highest = ptr->client_socket;
+                               ++numselect;
                        }
-               else {
-                       lprintf(7, "citserver: Client socket %d\n", ssock);
-                       con = CreateNewContext();
-                       con->client_socket = ssock;
-
-                       /* Set the SO_REUSEADDR socket option */
-                       i = 1;
-                       setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR,
-                               &i, sizeof(i));
-
-                       /* set attributes for the new thread */
-                       pthread_attr_init(&attr);
-                       pthread_attr_setdetachstate(&attr,
-                               PTHREAD_CREATE_DETACHED);
-
-                       /* now create the thread */
-                       if (pthread_create(&SessThread, &attr,
-                                          (void* (*)(void*)) sd_context_loop,
-                                          con)
-                           != 0) {
-                               lprintf(1,
-                                       "citserver: can't create thread: %s\n",
+               }
+               end_critical_section(S_SESSION_TABLE);
+
+               lprintf(9, "Thread %2d can wake up on %d different fd's\n",
+                       getpid(), numselect);
+               retval = select(highest + 1, &readfds, NULL, NULL, NULL);
+               lprintf(9, "select() returned %d\n", retval);
+
+               /* Now figure out who made this select() unblock.
+                * First, check for an error or exit condition.
+                */
+               if (retval < 0) {
+                       end_critical_section(S_I_WANNA_SELECT);
+                       lprintf(9, "Exiting (%s)\n", errno);
+                       time_to_die = 1;
+               }
+
+               /* Next, check to see if it's a new client connecting
+                * on the master socket.
+                */
+               else if (FD_ISSET(msock, &readfds)) {
+                       lprintf(9, "It's the master socket!\n");
+                       alen = sizeof fsin;
+                       ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
+                       if (ssock < 0) {
+                               lprintf(2, "citserver: accept() failed: %s\n",
                                        strerror(errno));
+                       }
+                       else {
+                               lprintf(7, "citserver: New client socket %d\n",
+                                       ssock);
+
+                               /* 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;
+       
+                               /* Set the SO_REUSEADDR socket option */
+                               i = 1;
+                               setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR,
+                                       &i, sizeof(i));
+
+                               pthread_setspecific(MyConKey, (void *)con);
+                               begin_session(con);
+                               /* do_command_loop(); */
+                               pthread_setspecific(MyConKey, (void *)NULL);
+                               con->state = CON_IDLE;
+                               goto SETUP_FD;
+                       }
+               }
+
+               /* If the rescan pipe went active, someone is telling this
+                * thread that the &readfds needs to be refreshed with more
+                * current data.
+                */
+               else if (FD_ISSET(rescan[0], &readfds)) {
+                       lprintf(9, "rescanning\n");
+                       read(rescan[0], &junk, 1);
+                       goto SETUP_FD;
+               }
+
+               /* It must be a client socket.  Find a context that has data
+                * waiting on its socket *and* is in the CON_IDLE state.
+                */
+               else {
+                       bind_me = NULL;
+                       begin_critical_section(S_SESSION_TABLE);
+                       for (ptr = ContextList;
+                           ( (ptr != NULL) && (bind_me == NULL) );
+                           ptr = ptr->next) {
+                               if ( (FD_ISSET(ptr->client_socket, &readfds))
+                                  && (ptr->state == CON_IDLE) ) {
+                                       bind_me = con;
                                }
+                       }
+                       if (bind_me != NULL) {
+                               /* Found one.  Stake a claim to it before
+                                * letting anyone else touch the context list.
+                                */
+                               bind_me->state = CON_EXECUTING;
+                       }
 
+                       end_critical_section(S_SESSION_TABLE);
+                       end_critical_section(S_I_WANNA_SELECT);
+
+                       /* We're bound to a session, now do *one* command */
+                       if (bind_me != NULL) {
+                               lprintf(9, "Binding thread to session %d\n",
+                                       bind_me->client_socket);
+                               pthread_setspecific(MyConKey, (void *)bind_me);
+                               do_command_loop();
+                               pthread_setspecific(MyConKey, (void *)NULL);
+                               if (bind_me->state == CON_DYING) {
+                                       RemoveContext(bind_me);
+                               } 
+                               else {
+                                       bind_me->state = CON_IDLE;
+                               }
+                               write(rescan[1], &junk, 1);
+                       }
+                       else {
+                               lprintf(9, "Thread %02d found nothing to do!\n",
+                                       getpid());
                        }
+
                }
-       master_cleanup();
-       return 0;
+
        }
 
+       pthread_exit(NULL);
+}
+
index 4f1587f8c2941a6dfb42f99906c8c38668f47ae3..ef5b9e700c1e5b5c370b46ae5eb18ffaf16d8cf0 100644 (file)
@@ -15,9 +15,9 @@ int client_read_to (char *buf, int bytes, int timeout);
 int client_read (char *buf, int bytes);
 int client_gets (char *buf);
 void sysdep_master_cleanup (void);
-void cleanup (int exit_code);
 void kill_session (int session_to_kill);
 void *sd_context_loop (struct CitContext *con);
 void start_daemon (int do_close_stdio);
 void cmd_nset (char *cmdbuf);
 int convert_login (char *NameToConvert);
+void worker_thread (void);