remove fd from poll list, before closing it, handle EBADF in select.

If select/poll fails for reason other than EINTR, make that error fatal.

git-svn-id: file:///var/lib/svn/clamav-devel/branches/clamd-proto@4623 77e5149b-7576-45b1-b177-96237e5ba77b
0.95
Török Edvin 17 years ago
parent 78e8d83a07
commit cb95779e9c
  1. 7
      ChangeLog
  2. 37
      clamd/others.c
  3. 1
      clamd/others.h
  4. 11
      clamd/server-th.c
  5. 1
      clamd/server.h

@ -1,3 +1,10 @@
Fri Jan 16 18:11:39 EET 2009 (edwin)
------------------------------------
* clamd/others.c, clamd/others.h, clamd/server-th.c, clamd/server.h:
remove fd from poll list, before closing it, handle EBADF in select.
If select/poll fails for reason other than EINTR, make that error
fatal.
Fri Jan 16 17:18:04 EET 2009 (edwin)
------------------------------------
* clamd/others.c: typo -> segfault -> fix

@ -356,6 +356,19 @@ int fds_add(struct fd_data *data, int fd, int listen_only)
return realloc_polldata(data);
}
void fds_remove(struct fd_data *data, int fd)
{
size_t i;
pthread_mutex_lock(&data->buf_mutex);
for (i=0;i<data->nfds;i++) {
if (data->buf[i].fd == fd) {
data->buf[i].fd = -1;
break;
}
}
pthread_mutex_unlock(&data->buf_mutex);
}
#define BUFFSIZE 1024
/* Wait till data is available to be read on any of the fds,
* read available data on all fds, and mark them as appropriate.
@ -475,6 +488,30 @@ int fds_poll_recv(struct fd_data *data, int timeout, int check_signals)
}
}
}
if (retval < 0 && errno == EBADF) {
/* unlike poll(), select() won't tell us which FD is bad, so
* we have to check them one by one. */
tv.tv_sec = 0;
tv.tv_usec = 0;
/* with tv == 0 it doesn't check for EBADF */
FD_ZERO(&rfds);
for (i=0; i< data->nfds; i++) {
if (data->buf[i].fd == -1)
continue;
FD_SET(data->buf[i].fd, &rfds);
do {
retval = select(data->buf[i].fd+1, &rfds, NULL, NULL, &tv);
} while (retval == -1 && errno == EINTR);
if (retval == -1) {
data->buf[i].fd = -1;
} else {
FD_CLR(data->buf[i].fd, &rfds);
}
}
retval = -1;
errno = EINTR;
continue;
}
} while (retval == -1 && !check_signals && errno == EINTR);
#endif

@ -48,6 +48,7 @@ int is_fd_connected(int fd);
void virusaction(const char *filename, const char *virname, const struct optstruct *opts);
int writen(int fd, void *buff, unsigned int count);
int fds_add(struct fd_data *data, int fd, int listen_only);
void fds_remove(struct fd_data *data, int fd);
int fds_poll_recv(struct fd_data *data, int timeout, int check_signals);
void fds_free(struct fd_data *data);

@ -146,6 +146,7 @@ static void scanner_thread(void *arg)
} while (session);
thrmgr_setactiveengine(NULL);
fds_remove(conn->fds, conn->sd);
shutdown(conn->sd, 2);
closesocket(conn->sd);
cl_engine_free(conn->engine);
@ -643,7 +644,6 @@ int acceptloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, un
/* Block waiting for connection on any of the sockets,
* doesn't wake on signals, that is what recvloop does! */
int new_sd = fds_poll_recv(&fds, -1, 1);
/* TODO: what about sockets that get rm-ed? */
if (!fds.nfds) {
/* no more sockets to poll, all gave an error */
@ -651,6 +651,13 @@ int acceptloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, un
break;
}
if (new_sd == -1 && errno != EINTR) {
logg("!Failed to poll sockets, fatal\n");
pthread_mutex_lock(&exit_mutex);
progexit = 1;
pthread_mutex_unlock(&exit_mutex);
}
for (i=0;i < fds.nfds && new_sd >= 0; i++) {
struct fd_buf *buf = &fds.buf[i];
if (!buf->got_newdata)
@ -693,6 +700,7 @@ int acceptloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, un
client_conn = (client_conn_t *) malloc(sizeof(struct client_conn_tag));
if(client_conn) {
client_conn->sd = buf->fd;
client_conn->fds = &fds;
client_conn->cmdlen = cmdlen;
client_conn->cmd = malloc(cmdlen+1);
client_conn->term = term;
@ -764,6 +772,7 @@ int acceptloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, un
shutdown(fds.buf[i].fd, 2);
closesocket(fds.buf[i].fd);
}
fds.nfds = 0;
break;
}
pthread_mutex_unlock(&exit_mutex);

@ -47,6 +47,7 @@ typedef struct client_conn_tag {
char *cmd;
size_t cmdlen;
int sd;
struct fd_data *fds;
unsigned int options;
const struct optstruct *opts;
struct cl_engine *engine;

Loading…
Cancel
Save