Reimplement max_idle without a separate thread
Remove the KillIdle thread. Add timeout to struct iop, initialized in io_open(). Obey it in io_input() by passing it to empth_select(). If empth_select() times out, report that back through io_input() to recvclient() and player_login(). If player_login() receives a timeout indication, print a message and terminate the session. If recvclient() receives a timeout indication, flash a message to the player and initiate a shut down the player's session. Create WIN32 sys/time.h to define struct timeval. This creates some conflicts with WIN32 windows.h definitions. Including windows.h in show.c and info.c creates conflicts, so remove that. Modify service.c to include sys/socket.h instead of windows.h to remove the conflict with sys/time.h.
This commit is contained in:
parent
a7ee69d112
commit
08b9455682
17 changed files with 181 additions and 133 deletions
|
@ -61,6 +61,7 @@ struct iop {
|
|||
struct ioqueue *output;
|
||||
int flags;
|
||||
int bufsize;
|
||||
struct timeval input_timeout;
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -69,7 +70,7 @@ io_init(void)
|
|||
}
|
||||
|
||||
struct iop *
|
||||
io_open(int fd, int flags, int bufsize)
|
||||
io_open(int fd, int flags, int bufsize, struct timeval timeout)
|
||||
{
|
||||
struct iop *iop;
|
||||
|
||||
|
@ -83,6 +84,7 @@ io_open(int fd, int flags, int bufsize)
|
|||
iop->input = 0;
|
||||
iop->output = 0;
|
||||
iop->flags = 0;
|
||||
iop->input_timeout = timeout;
|
||||
iop->bufsize = bufsize;
|
||||
if ((flags & IO_READ) && (flags & IO_NEWSOCK) == 0)
|
||||
iop->input = ioq_create(bufsize);
|
||||
|
@ -106,31 +108,47 @@ io_close(struct iop *iop)
|
|||
free(iop);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return number of bytes read on success, zero on timeout or EOF, -1
|
||||
* on error, with errno set appropriately. In particular, return -1
|
||||
* with errno set to EAGAIN or EWOULDBLOCK when no data is available
|
||||
* for non-blocking input (WAITFORINPUT false). Use io_eof() to
|
||||
* distinguish timeout from EOF.
|
||||
*/
|
||||
int
|
||||
io_input(struct iop *iop, int waitforinput)
|
||||
{
|
||||
char buf[IO_BUFSIZE];
|
||||
int cc;
|
||||
int res;
|
||||
struct timeval timeout = iop->input_timeout;
|
||||
|
||||
/* Not a read IOP */
|
||||
if ((iop->flags & IO_READ) == 0)
|
||||
if ((iop->flags & IO_READ) == 0) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
/* IOP is markes as in error. */
|
||||
if (iop->flags & IO_ERROR)
|
||||
if (iop->flags & IO_ERROR) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
/* Wait for the file to have input. */
|
||||
if (waitforinput) {
|
||||
empth_select(iop->fd, EMPTH_FD_READ);
|
||||
res = empth_select(iop->fd, EMPTH_FD_READ, &timeout);
|
||||
if (res < 0) {
|
||||
iop->flags |= IO_ERROR;
|
||||
return -1;
|
||||
} else if (res == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Do the actual read. */
|
||||
cc = read(iop->fd, buf, sizeof(buf));
|
||||
if (cc < 0) {
|
||||
/* would block, so nothing to read. */
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
return 0;
|
||||
|
||||
/* Some form of file error occurred... */
|
||||
iop->flags |= IO_ERROR;
|
||||
if (errno != EAGAIN && errno != EWOULDBLOCK)
|
||||
/* Some form of file error occurred... */
|
||||
iop->flags |= IO_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -190,7 +208,7 @@ io_output(struct iop *iop, int waitforoutput)
|
|||
if (waitforoutput != IO_NOWAIT) {
|
||||
/* This waits for the file to be ready for writing, */
|
||||
/* and lets other threads run. */
|
||||
empth_select(iop->fd, EMPTH_FD_WRITE);
|
||||
empth_select(iop->fd, EMPTH_FD_WRITE, NULL);
|
||||
}
|
||||
|
||||
/* Do the actual write. */
|
||||
|
@ -272,7 +290,7 @@ io_output_all(struct iop *iop)
|
|||
* a malicous player could delay the update indefinitely
|
||||
*/
|
||||
while ((n = io_output(iop, IO_NOWAIT)) > 0 && !play_wrlock_wanted)
|
||||
empth_select(iop->fd, EMPTH_FD_WRITE);
|
||||
empth_select(iop->fd, EMPTH_FD_WRITE, NULL);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -104,10 +104,10 @@ empth_terminate(empth_t *a)
|
|||
lwpTerminate(a);
|
||||
}
|
||||
|
||||
void
|
||||
empth_select(int fd, int flags)
|
||||
int
|
||||
empth_select(int fd, int flags, struct timeval *timeout)
|
||||
{
|
||||
lwpSleepFd(fd, flags);
|
||||
return lwpSleepFd(fd, flags, timeout);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -560,12 +560,14 @@ empth_terminate(empth_t *pThread)
|
|||
*
|
||||
* This would be one of the main functions used within gen\io.c
|
||||
*/
|
||||
void
|
||||
empth_select(int fd, int flags)
|
||||
int
|
||||
empth_select(int fd, int flags, struct timeval *timeout)
|
||||
{
|
||||
int handle;
|
||||
WSAEVENT hEventObject[2];
|
||||
DWORD result, msec;
|
||||
empth_t *pThread = TlsGetValue(dwTLSIndex);
|
||||
int res;
|
||||
|
||||
loc_debug("%s select on %d",
|
||||
flags == EMPTH_FD_READ ? "read" : "write", fd);
|
||||
|
@ -586,13 +588,31 @@ empth_select(int fd, int flags)
|
|||
empth_exit();
|
||||
}
|
||||
|
||||
WSAWaitForMultipleEvents(2, hEventObject, FALSE, WSA_INFINITE, FALSE);
|
||||
if (timeout)
|
||||
msec = timeout->tv_sec * 1000L + timeout->tv_usec / 1000L;
|
||||
else
|
||||
msec = WSA_INFINITE;
|
||||
result = WSAWaitForMultipleEvents(2, hEventObject, FALSE, msec,
|
||||
FALSE);
|
||||
|
||||
switch (result) {
|
||||
case WSA_WAIT_TIMEOUT:
|
||||
res = 0;
|
||||
break;
|
||||
case WSA_WAIT_FAILED:
|
||||
errno = WSAGetLastError();
|
||||
res = -1;
|
||||
break;
|
||||
default:
|
||||
res = 1;
|
||||
}
|
||||
|
||||
WSAEventSelect(handle, hEventObject[0], 0);
|
||||
|
||||
WSACloseEvent(hEventObject[0]);
|
||||
|
||||
loc_RunThisThread(NULL);
|
||||
return res;
|
||||
}
|
||||
|
||||
/************************
|
||||
|
|
|
@ -289,65 +289,58 @@ empth_terminate(empth_t *a)
|
|||
pthread_kill(a->id, SIGALRM);
|
||||
}
|
||||
|
||||
void
|
||||
empth_select(int fd, int flags)
|
||||
int
|
||||
empth_select(int fd, int flags, struct timeval *tv)
|
||||
{
|
||||
|
||||
fd_set readmask;
|
||||
fd_set writemask;
|
||||
struct timeval tv;
|
||||
int n;
|
||||
int res = 0;
|
||||
|
||||
pthread_mutex_unlock(&mtx_ctxsw);
|
||||
empth_status("%s select on %d",
|
||||
flags == EMPTH_FD_READ ? "read" : "write", fd);
|
||||
while (1) {
|
||||
tv.tv_sec = 1000000;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
FD_ZERO(&readmask);
|
||||
FD_ZERO(&writemask);
|
||||
FD_ZERO(&readmask);
|
||||
FD_ZERO(&writemask);
|
||||
|
||||
switch (flags) {
|
||||
case EMPTH_FD_READ:
|
||||
FD_SET(fd, &readmask);
|
||||
break;
|
||||
case EMPTH_FD_WRITE:
|
||||
FD_SET(fd, &writemask);
|
||||
break;
|
||||
default:
|
||||
logerror("bad flag %d passed to empth_select", flags);
|
||||
empth_exit();
|
||||
}
|
||||
|
||||
n = select(fd + 1, &readmask, &writemask, (fd_set *) 0, &tv);
|
||||
|
||||
if (n < 0) {
|
||||
if (errno == EINTR) {
|
||||
/* go handle the signal */
|
||||
empth_status("select broken by signal");
|
||||
goto done;
|
||||
return;
|
||||
}
|
||||
/* strange but we dont get EINTR on select broken by signal */
|
||||
empth_status("select failed (%s)", strerror(errno));
|
||||
goto done;
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags == EMPTH_FD_READ && FD_ISSET(fd, &readmask)) {
|
||||
empth_status("input ready");
|
||||
break;
|
||||
}
|
||||
if (flags == EMPTH_FD_WRITE && FD_ISSET(fd, &writemask)) {
|
||||
empth_status("output ready");
|
||||
break;
|
||||
}
|
||||
switch (flags) {
|
||||
case EMPTH_FD_READ:
|
||||
FD_SET(fd, &readmask);
|
||||
break;
|
||||
case EMPTH_FD_WRITE:
|
||||
FD_SET(fd, &writemask);
|
||||
break;
|
||||
default:
|
||||
CANT_REACH();
|
||||
errno = EINVAL;
|
||||
res = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
n = select(fd + 1, &readmask, &writemask, (fd_set *) 0, tv);
|
||||
|
||||
if (n < 0) {
|
||||
if (errno == EINTR) /* go handle the signal */
|
||||
empth_status("select broken by signal");
|
||||
else
|
||||
empth_status("select failed (%s)", strerror(errno));
|
||||
res = -1;
|
||||
} else if (n == 0) {
|
||||
empth_status("select timed out");
|
||||
res = 0;
|
||||
} else if (flags == EMPTH_FD_READ && FD_ISSET(fd, &readmask)) {
|
||||
empth_status("input ready");
|
||||
res = 1;
|
||||
} else if (flags == EMPTH_FD_WRITE && FD_ISSET(fd, &writemask)) {
|
||||
empth_status("output ready");
|
||||
res = 1;
|
||||
}
|
||||
|
||||
done:
|
||||
pthread_mutex_lock(&mtx_ctxsw);
|
||||
empth_restorectx();
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue