aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2011-07-08 18:47:50 +0200
committerSverker Eriksson <[email protected]>2011-07-27 11:41:26 +0200
commita6e8634b84f564ec62e44f7c91a1c400af3dd347 (patch)
tree38ae7f65b568f45256e247bbbb0da56c7c9ee05c
parent089b8c357f5e7c96605c8f8cab4b3c856081dc39 (diff)
downloadotp-a6e8634b84f564ec62e44f7c91a1c400af3dd347.tar.gz
otp-a6e8634b84f564ec62e44f7c91a1c400af3dd347.tar.bz2
otp-a6e8634b84f564ec62e44f7c91a1c400af3dd347.zip
Fix epmd crash on vxworks caused by faulty argument to select
The first argument g->max_conn to select() in epmd_srv.c seems to be wrong as it excludes the listening socket(s). Instead we keep track of the highest fd seen. However I still don't understand why select() started to fail for vxworks with R14B03 when the feature of more than one listening socket was introduced. The default is still 1 listening socket (num_sockets=1), which would make the first argument to select() unchanged.
-rw-r--r--erts/epmd/src/epmd_int.h9
-rw-r--r--erts/epmd/src/epmd_srv.c20
2 files changed, 24 insertions, 5 deletions
diff --git a/erts/epmd/src/epmd_int.h b/erts/epmd/src/epmd_int.h
index 2a0de4df9c..a2d7559f9d 100644
--- a/erts/epmd/src/epmd_int.h
+++ b/erts/epmd/src/epmd_int.h
@@ -240,6 +240,14 @@
#define put_int16(i, s) {((unsigned char*)(s))[0] = ((i) >> 8) & 0xff; \
((unsigned char*)(s))[1] = (i) & 0xff;}
+#if defined(__GNUC__)
+# define EPMD_INLINE __inline__
+#elif defined(__WIN32__)
+# define EPMD_INLINE __inline
+#else
+# define EPMD_INLINE
+#endif
+
/* ************************************************************************ */
/* Stuctures used by server */
@@ -295,6 +303,7 @@ typedef struct {
unsigned delay_write;
int max_conn;
int active_conn;
+ int select_fd_top;
char *progname;
Connection *conn;
Nodes nodes;
diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c
index 4d9b454f97..5debae26b6 100644
--- a/erts/epmd/src/epmd_srv.c
+++ b/erts/epmd/src/epmd_srv.c
@@ -80,6 +80,13 @@ static int reply(EpmdVars*,int,char *,int);
static void dbg_print_buf(EpmdVars*,char *,int);
static void print_names(EpmdVars*);
+static EPMD_INLINE void select_fd_set(EpmdVars* g, int fd)
+{
+ FD_SET(fd, &g->orig_read_mask);
+ if (fd >= g->select_fd_top) {
+ g->select_fd_top = fd + 1;
+ }
+}
void run(EpmdVars *g)
{
@@ -171,6 +178,7 @@ void run(EpmdVars *g)
g->max_conn -= num_sockets;
FD_ZERO(&g->orig_read_mask);
+ g->select_fd_top = 0;
for (i = 0; i < num_sockets; i++)
{
@@ -232,14 +240,14 @@ void run(EpmdVars *g)
dbg_perror(g,"failed to listen on socket");
epmd_cleanup_exit(g,1);
}
- FD_SET(listensock[i],&g->orig_read_mask);
+ select_fd_set(g, listensock[i]);
}
dbg_tty_printf(g,2,"entering the main select() loop");
select_again:
while(1)
- {
+ {
fd_set read_mask = g->orig_read_mask;
struct timeval timeout;
int ret;
@@ -251,7 +259,8 @@ void run(EpmdVars *g)
timeout.tv_sec = (g->packet_timeout < IDLE_TIMEOUT) ? 1 : IDLE_TIMEOUT;
timeout.tv_usec = 0;
- if ((ret = select(g->max_conn,&read_mask,(fd_set *)0,(fd_set *)0,&timeout)) < 0) {
+ if ((ret = select(g->select_fd_top,
+ &read_mask, (fd_set *)0,(fd_set *)0,&timeout)) < 0) {
dbg_perror(g,"error in select ");
switch (errno) {
case EAGAIN:
@@ -821,7 +830,7 @@ static int conn_open(EpmdVars *g,int fd)
s = &g->conn[i];
/* From now on we want to know if there are data to be read */
- FD_SET(fd, &g->orig_read_mask);
+ select_fd_set(g, fd);
s->fd = fd;
s->open = EPMD_TRUE;
@@ -886,6 +895,7 @@ int epmd_conn_close(EpmdVars *g,Connection *s)
dbg_tty_printf(g,2,"closing connection on file descriptor %d",s->fd);
FD_CLR(s->fd,&g->orig_read_mask);
+ /* we don't bother lowering g->select_fd_top */
close(s->fd); /* Sometimes already closed but close anyway */
s->open = EPMD_FALSE;
if (s->buf != NULL) { /* Should never be NULL but test anyway */
@@ -1115,7 +1125,7 @@ static Node *node_reg2(EpmdVars *g,
node->extralen = extralen;
memcpy(node->extra,extra,extralen);
strcpy(node->symname,name);
- FD_SET(fd,&g->orig_read_mask);
+ select_fd_set(g, fd);
if (highvsn == 0) {
dbg_tty_printf(g,1,"registering '%s:%d', port %d",