Update of /cvsroot/netrek/client/netrekxp/src In directory sc8-pr-cvs16:/tmp/cvs-serv1445/src Modified Files: cowmain.c data.c death.c input.c socket.c Log Message: Terminate() calls within the network thread were causing errors due to longjump() into the input thread. A new function, terminate2() deals with such cases. Instead of calling longjump() directly, the main thread is exited via W_TerminateWait() and ExitThread() calls, and a global error variable is used to pass the exit code to setjmp in cowmain.c This bit of code was previously used in death.c to handle jumping out of the network thread to the main thread upon being sent to the team select entry window. All terminate() calls in socket.c have been modified to use the appropriate version (terminate/terminate2) depending on if THREADED is defined. Index: input.c =================================================================== RCS file: /cvsroot/netrek/client/netrekxp/src/input.c,v retrieving revision 1.37 retrieving revision 1.38 diff -u -d -r1.37 -r1.38 --- input.c 23 Apr 2007 07:19:30 -0000 1.37 +++ input.c 28 Apr 2007 12:09:51 -0000 1.38 @@ -719,7 +719,7 @@ W_NextEvent (&event); ingame = 0; - longjmp (env, 0); + longjmp (env, globalerr); } /******************************************************************************/ Index: death.c =================================================================== RCS file: /cvsroot/netrek/client/netrekxp/src/death.c,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- death.c 6 Apr 2007 06:46:31 -0000 1.18 +++ death.c 28 Apr 2007 12:09:51 -0000 1.19 @@ -246,15 +246,8 @@ longjmp (env, 0); #else - /* Threaded: when using threads, this thread has been spawned to handle network - I/O and so we cannot longjmp here, into another thread! Instead we call - W_TerminateWait which makes the main thead's W_WaitForEvent() return 0 - and exitthread */ - if (!playback) - { /* If we are not playing back a recorded game, do this */ - W_TerminateWait (); - ExitThread (0); - } + if (!playback) /* If we are not playing back a recorded game, do this */ + terminate2 (0); else { /* Otherwise we aren't within a thread, so... */ while (W_EventsPending ()) Index: data.c =================================================================== RCS file: /cvsroot/netrek/client/netrekxp/src/data.c,v retrieving revision 1.89 retrieving revision 1.90 diff -u -d -r1.89 -r1.90 --- data.c 27 Apr 2007 07:15:28 -0000 1.89 +++ data.c 28 Apr 2007 12:09:51 -0000 1.90 @@ -35,6 +35,7 @@ int TWINSIDE = 500; /* Size of tactical window */ int GWINSIDE = 500; /* Size of galactic window */ +int globalerr = 0; /* For sending error # between threads */ int ingame = 0; /* If player is in game - to distinguish between whether to use double buffering on the local and map window */ int ghoststart = 0; /* is this a ghostbust Index: cowmain.c =================================================================== RCS file: /cvsroot/netrek/client/netrekxp/src/cowmain.c,v retrieving revision 1.33 retrieving revision 1.34 diff -u -d -r1.33 -r1.34 --- cowmain.c 19 Apr 2007 08:22:58 -0000 1.33 +++ cowmain.c 28 Apr 2007 12:09:51 -0000 1.34 @@ -42,7 +42,6 @@ int isFirstEntry; char defaulttmp[100]; -#define RETURNBASE 10 #ifdef PACKET_LOG extern int log_packets; #endif @@ -1101,3 +1100,21 @@ { longjmp (env, RETURNBASE + error); } + +#ifdef THREADED +/******************************************************************************/ +/*** terminate2() - for terminating inside the network thread ***/ +/******************************************************************************/ +void +terminate2 (int error) +{ + /* When using threads, a thread has been spawned to handle network + I/O and so we cannot longjmp into another thread! Instead we call + W_TerminateWait which makes the main thread's W_WaitForEvent() + return 0 and exitthread. We pass the desired error value + to longjmp in input() via globalerr. */ + globalerr = error; + W_TerminateWait (); + ExitThread (0); +} +#endif \ No newline at end of file Index: socket.c =================================================================== RCS file: /cvsroot/netrek/client/netrekxp/src/socket.c,v retrieving revision 1.30 retrieving revision 1.31 diff -u -d -r1.30 -r1.31 --- socket.c 25 Apr 2007 06:50:43 -0000 1.30 +++ socket.c 28 Apr 2007 12:09:51 -0000 1.31 @@ -560,7 +560,11 @@ if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0) { LineToConsole ("I can't create a socket\n"); +#ifdef THREADED + terminate2 (RETURNBASE + 2); +#else terminate (2); +#endif } /* allow local address resuse */ @@ -577,9 +581,12 @@ if (bind (s, (struct sockaddr *) &addr, sizeof (addr)) < 0) { - perror ("bind"); /* NEW */ +#ifdef THREADED + terminate2 (RETURNBASE + 1); +#else terminate (1); +#endif } if (listen (s, 1) < 0) perror ("listen"); @@ -598,7 +605,11 @@ if (select (max_fd, &readfds, NULL, NULL, &timeout) == 0) { LineToConsole ("Well, I think the server died!\n"); +#ifdef THREADED + terminate2 (RETURNBASE); +#else terminate (0); +#endif } sock = accept (s, (struct sockaddr *) &naddr, &len); @@ -664,7 +675,11 @@ if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0) { LineToConsole ("I can't create a socket\n"); +#ifdef THREADED + terminate2 (RETURNBASE); +#else terminate (0); +#endif } addr.sin_family = AF_INET; addr.sin_port = htons ((u_short) port); @@ -674,7 +689,11 @@ if ((hp = gethostbyname (server)) == NULL) { LineToConsole ("Who is %s?\n", server); +#ifdef THREADED + terminate2 (RETURNBASE); +#else terminate (0); +#endif } else { @@ -686,7 +705,11 @@ if (connect (s, (struct sockaddr *) &addr, sizeof (addr)) < 0) { LineToConsole ("Server not listening!\n"); +#ifdef THREADED + terminate2 (RETURNBASE); +#else terminate (0); +#endif } LineToConsole ("Got connection.\n"); @@ -721,7 +744,11 @@ if (gwrite (s, &msg, sizeof (struct mesg_cpacket)) < 0) { LineToConsole ("trekhopd init failure\n"); +#ifdef THREADED + terminate2 (RETURNBASE + 1); +#else terminate (1); +#endif } LineToConsole ("--- trekhopd request sent, awaiting reply\n"); /* now block waiting for reply */ @@ -732,7 +759,11 @@ if ((n = recv (s, buf, count, 0)) <= 0) { perror ("trekhopd read"); +#ifdef THREADED + terminate2 (RETURNBASE + 1); +#else terminate (1); +#endif } } @@ -740,7 +771,11 @@ { LineToConsole ("Got bogus reply from trekhopd (%d)\n", reply.type); +#ifdef THREADED + terminate2 (RETURNBASE + 1); +#else terminate (1); +#endif } ip = (int *) reply.mesg; gw_serv_port = ntohl (*ip++); @@ -2177,7 +2212,11 @@ LineToConsole ("Unknown message from handleBadVersion.\n"); return; } +#ifdef THREADED + terminate2 (RETURNBASE + 1); +#else terminate (1); +#endif } long @@ -2563,7 +2602,11 @@ if (getpeername (sock, (struct sockaddr *) &saddr, &len) < 0) { perror ("getpeername(sock)"); +#ifdef THREADED + terminate2 (RETURNBASE + 1); +#else terminate (1); +#endif } } else @@ -2577,7 +2620,11 @@ if (getpeername (sock, (struct sockaddr *) &saddr, &len) < 0) { perror ("getpeername(sock)"); +#ifdef THREADED + terminate2 (RETURNBASE + 1); +#else terminate (1); +#endif } #endif @@ -2945,7 +2992,11 @@ if ((hp = gethostbyname (serverName)) == NULL) { LineToConsole ("Who is %s?\n", serverName); +#ifdef THREADED + terminate2 (RETURNBASE); +#else terminate (0); +#endif } else {