Commit 3de05e2d authored by Deucе's avatar Deucе 👌🏾
Browse files

Use new PREFER_POLL define to control poll() usage

Rather than depending on _WIN32 which is silly, make it clear what
exactly is being done and why.

Note that the spy socket stuff and some external stuff on *nix have
had the select() implementation removed.  To support using select()
on !Win32 will require de-refactoring that's not really worth doing.
Instead, just use #error and reference the commit where the old
code can be found.
parent f203d5df
Pipeline #1695 failed with stage
in 10 minutes and 30 seconds
......@@ -214,6 +214,10 @@ ifndef os
endif
os := $(shell echo $(os) | tr '[A-Z]' '[a-z]' | tr ' ' '_')
ifneq ($(os),Win32)
CFLAGS += -DPREFER_POLL
endif
machine := $(shell if uname -m | egrep -v "(i[3456789]*|x)86" > /dev/null; then uname -m | tr "[A-Z]" "[a-z]" | tr " " "_" ; fi)
machine := $(shell if uname -m | egrep "64" > /dev/null; then uname -m | tr "[A-Z]" "[a-z]" | tr " " "_" ; else echo $(machine) ; fi)
ifeq ($(os),darwin)
......
......@@ -3695,19 +3695,19 @@ js_socket_select(JSContext *cx, uintN argc, jsval *arglist)
JSObject* robj;
JSObject* rarray;
BOOL poll_for_write=FALSE;
#ifdef _WIN32
fd_set socket_set[3];
fd_set* sets[3] = {NULL, NULL, NULL};
SOCKET maxsock=0;
struct timeval tv = {0, 0};
SOCKET sock;
#else
#ifdef PREFER_POLL
struct pollfd *fds;
int poll_timeout = 0;
nfds_t nfds;
short events;
int scount;
int k;
#else
fd_set socket_set[3];
fd_set* sets[3] = {NULL, NULL, NULL};
SOCKET maxsock=0;
struct timeval tv = {0, 0};
SOCKET sock;
#endif
uintN argn;
jsuint i;
......@@ -3726,12 +3726,12 @@ js_socket_select(JSContext *cx, uintN argc, jsval *arglist)
poll_for_write=JSVAL_TO_BOOLEAN(argv[argn]);
else if(JSVAL_IS_OBJECT(argv[argn]))
inarray[inarray_cnt++] = JSVAL_TO_OBJECT(argv[argn]);
#ifdef _WIN32
#ifdef PREFER_POLL
else if(JSVAL_IS_NUMBER(argv[argn]))
js_timeval(cx,argv[argn],&tv);
poll_timeout = js_polltimeout(cx, argv[argn]);
#else
else if(JSVAL_IS_NUMBER(argv[argn]))
poll_timeout = js_polltimeout(cx, argv[argn]);
js_timeval(cx,argv[argn],&tv);
#endif
}
......@@ -3753,42 +3753,7 @@ js_socket_select(JSContext *cx, uintN argc, jsval *arglist)
/* Return array */
if((robj = JS_NewArrayObject(cx, 0, NULL))==NULL)
return(JS_FALSE);
#ifdef _WIN32
FD_ZERO(&socket_set[0]);
if(poll_for_write)
sets[1]=&socket_set[0];
else
sets[0]=&socket_set[0];
for(i=0;i<limit[0];i++) {
if(!JS_GetElement(cx, inarray[0], i, &val))
break;
sock=js_socket_add(cx,val,&socket_set[0]);
if(sock!=INVALID_SOCKET) {
if(sock>maxsock)
maxsock=sock;
}
}
rc=JS_SUSPENDREQUEST(cx);
if(select(maxsock+1,sets[0],sets[1],sets[2],&tv) >= 0) {
for(i=0;i<limit[0];i++) {
if(!JS_GetElement(cx, inarray[0], i, &val))
break;
if(js_socket_isset(cx,val,&socket_set[0])) {
val=INT_TO_JSVAL(i);
JS_RESUMEREQUEST(cx, rc);
if(!JS_SetElement(cx, robj, len++, &val)) {
rc=JS_SUSPENDREQUEST(cx);
break;
}
rc=JS_SUSPENDREQUEST(cx);
}
}
JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(robj));
}
#else
#ifdef PREFER_POLL
// First, count the number of sockets...
nfds = 0;
for (i = 0; i < limit[0]; i++) {
......@@ -3837,66 +3802,51 @@ js_socket_select(JSContext *cx, uintN argc, jsval *arglist)
JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(robj));
}
free(fds);
#endif
JS_RESUMEREQUEST(cx, rc);
#else
FD_ZERO(&socket_set[0]);
if(poll_for_write)
sets[1]=&socket_set[0];
else
sets[0]=&socket_set[0];
return(JS_TRUE);
}
else {
/* Return object */
if((robj = JS_NewObject(cx, NULL, NULL, NULL))==NULL)
return(JS_FALSE);
#ifdef _WIN32
for (j = 0; j < inarray_cnt; j++) {
if (limit[j] > 0) {
FD_ZERO(&socket_set[j]);
sets[j] = &socket_set[j];
for (i = 0; i < limit[j]; i++) {
if(!JS_GetElement(cx, inarray[j], i, &val))
break;
sock=js_socket_add(cx,val,&socket_set[j]);
if(sock!=INVALID_SOCKET) {
if(sock>maxsock)
maxsock=sock;
}
}
for(i=0;i<limit[0];i++) {
if(!JS_GetElement(cx, inarray[0], i, &val))
break;
sock=js_socket_add(cx,val,&socket_set[0]);
if(sock!=INVALID_SOCKET) {
if(sock>maxsock)
maxsock=sock;
}
}
rc=JS_SUSPENDREQUEST(cx);
if(select(maxsock+1,sets[0],sets[1],sets[2],&tv) >= 0) {
for (j = 0; j < inarray_cnt; j++) {
if (limit[j] > 0) {
len = 0;
for(i=0;i<limit[0];i++) {
if(!JS_GetElement(cx, inarray[0], i, &val))
break;
if(js_socket_isset(cx,val,&socket_set[0])) {
val=INT_TO_JSVAL(i);
JS_RESUMEREQUEST(cx, rc);
if((rarray = JS_NewArrayObject(cx, 0, NULL))==NULL)
return(JS_FALSE);
val = OBJECT_TO_JSVAL(rarray);
if (!JS_SetProperty(cx, robj, props[j], &val))
return JS_FALSE;
rc=JS_SUSPENDREQUEST(cx);
for(i=0;i<limit[j];i++) {
JS_RESUMEREQUEST(cx, rc);
if(!JS_GetElement(cx, inarray[j], i, &val)) {
rc=JS_SUSPENDREQUEST(cx);
break;
}
if(!JS_SetElement(cx, robj, len++, &val)) {
rc=JS_SUSPENDREQUEST(cx);
if(js_socket_isset(cx,val,&socket_set[j])) {
val=INT_TO_JSVAL(i);
JS_RESUMEREQUEST(cx, rc);
if(!JS_SetElement(cx, rarray, len++, &val)) {
rc=JS_SUSPENDREQUEST(cx);
break;
}
rc=JS_SUSPENDREQUEST(cx);
}
break;
}
rc=JS_SUSPENDREQUEST(cx);
}
}
JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(robj));
}
#else
#endif
JS_RESUMEREQUEST(cx, rc);
return(JS_TRUE);
}
else {
/* Return object */
if((robj = JS_NewObject(cx, NULL, NULL, NULL))==NULL)
return(JS_FALSE);
#ifdef PREFER_POLL
/*
* So, we need to collapse all the FDs into a list with flags set...
* readfd corresponds to POLLIN
......@@ -4011,6 +3961,56 @@ js_socket_select(JSContext *cx, uintN argc, jsval *arglist)
JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(robj));
}
free(fds);
#else
for (j = 0; j < inarray_cnt; j++) {
if (limit[j] > 0) {
FD_ZERO(&socket_set[j]);
sets[j] = &socket_set[j];
for (i = 0; i < limit[j]; i++) {
if(!JS_GetElement(cx, inarray[j], i, &val))
break;
sock=js_socket_add(cx,val,&socket_set[j]);
if(sock!=INVALID_SOCKET) {
if(sock>maxsock)
maxsock=sock;
}
}
}
}
rc=JS_SUSPENDREQUEST(cx);
if(select(maxsock+1,sets[0],sets[1],sets[2],&tv) >= 0) {
for (j = 0; j < inarray_cnt; j++) {
if (limit[j] > 0) {
len = 0;
JS_RESUMEREQUEST(cx, rc);
if((rarray = JS_NewArrayObject(cx, 0, NULL))==NULL)
return(JS_FALSE);
val = OBJECT_TO_JSVAL(rarray);
if (!JS_SetProperty(cx, robj, props[j], &val))
return JS_FALSE;
rc=JS_SUSPENDREQUEST(cx);
for(i=0;i<limit[j];i++) {
JS_RESUMEREQUEST(cx, rc);
if(!JS_GetElement(cx, inarray[j], i, &val)) {
rc=JS_SUSPENDREQUEST(cx);
break;
}
rc=JS_SUSPENDREQUEST(cx);
if(js_socket_isset(cx,val,&socket_set[j])) {
val=INT_TO_JSVAL(i);
JS_RESUMEREQUEST(cx, rc);
if(!JS_SetElement(cx, rarray, len++, &val)) {
rc=JS_SUSPENDREQUEST(cx);
break;
}
rc=JS_SUSPENDREQUEST(cx);
}
}
}
}
JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(robj));
}
#endif
JS_RESUMEREQUEST(cx, rc);
......
......@@ -472,14 +472,15 @@ SOCKET DLLCALL js_socket(JSContext *cx, jsval val)
return(sock);
}
#ifdef _WIN32
SOCKET DLLCALL js_socket_add(JSContext *cx, jsval val, fd_set *fds)
#ifdef PREFER_POLL
size_t DLLCALL js_socket_numsocks(JSContext *cx, jsval val)
{
js_socket_private_t *p;
JSClass* cl;
SOCKET sock=INVALID_SOCKET;
size_t i;
int32_t intval;
size_t ret = 0;
if(JSVAL_IS_OBJECT(val) && (cl=JS_GetClass(cx,JSVAL_TO_OBJECT(val)))!=NULL) {
if(cl->flags&JSCLASS_HAS_PRIVATE) {
......@@ -488,33 +489,33 @@ SOCKET DLLCALL js_socket_add(JSContext *cx, jsval val, fd_set *fds)
for(i=0; i<p->set->sock_count; i++) {
if(p->set->socks[i].sock == INVALID_SOCKET)
continue;
FD_SET(p->set->socks[i].sock, fds);
if(p->set->socks[i].sock > sock)
sock = p->set->socks[i].sock;
ret++;
}
}
else {
sock = p->sock;
if(sock != INVALID_SOCKET)
FD_SET(p->sock, fds);
ret = 1;
}
}
}
} else if(val!=JSVAL_VOID) {
if(JS_ValueToInt32(cx,val,&intval)) {
sock = intval;
FD_SET(sock, fds);
if (intval != INVALID_SOCKET)
ret = 1;
}
}
return sock;
return ret;
}
BOOL DLLCALL js_socket_isset(JSContext *cx, jsval val, fd_set *fds)
size_t DLLCALL js_socket_add(JSContext *cx, jsval val, struct pollfd *fds, short events)
{
js_socket_private_t *p;
JSClass* cl;
SOCKET sock=INVALID_SOCKET;
size_t i;
int intval;
int32_t intval;
size_t ret = 0;
if(JSVAL_IS_OBJECT(val) && (cl=JS_GetClass(cx,JSVAL_TO_OBJECT(val)))!=NULL) {
if(cl->flags&JSCLASS_HAS_PRIVATE) {
......@@ -523,51 +524,38 @@ BOOL DLLCALL js_socket_isset(JSContext *cx, jsval val, fd_set *fds)
for(i=0; i<p->set->sock_count; i++) {
if(p->set->socks[i].sock == INVALID_SOCKET)
continue;
if(FD_ISSET(p->set->socks[i].sock, fds))
return TRUE;
fds[ret].events = events;
fds[ret++].fd = p->set->socks[i].sock;
}
}
else {
if (p->sock == INVALID_SOCKET)
return TRUE;
else {
if(FD_ISSET(p->sock, fds))
return TRUE;
sock = p->sock;
if(sock != INVALID_SOCKET) {
fds[ret].events = events;
fds[ret++].fd = sock;
}
}
}
}
} else if(val!=JSVAL_VOID) {
if(JS_ValueToInt32(cx,val,&intval)) {
if(FD_ISSET(intval, fds))
return TRUE;
}
}
return FALSE;
}
void DLLCALL js_timeval(JSContext* cx, jsval val, struct timeval* tv)
{
jsdouble jsd;
if(JSVAL_IS_INT(val))
tv->tv_sec = JSVAL_TO_INT(val);
else if(JSVAL_IS_DOUBLE(val)) {
if(JS_ValueToNumber(cx,val,&jsd)) {
tv->tv_sec = (int)jsd;
tv->tv_usec = (int)(jsd*1000000.0)%1000000;
sock = intval;
if(sock != INVALID_SOCKET) {
fds[ret].events = events;
fds[ret++].fd = sock;
}
}
}
return ret;
}
#else
size_t DLLCALL js_socket_numsocks(JSContext *cx, jsval val)
SOCKET DLLCALL js_socket_add(JSContext *cx, jsval val, fd_set *fds)
{
js_socket_private_t *p;
JSClass* cl;
SOCKET sock=INVALID_SOCKET;
size_t i;
int32_t intval;
size_t ret = 0;
if(JSVAL_IS_OBJECT(val) && (cl=JS_GetClass(cx,JSVAL_TO_OBJECT(val)))!=NULL) {
if(cl->flags&JSCLASS_HAS_PRIVATE) {
......@@ -576,33 +564,33 @@ size_t DLLCALL js_socket_numsocks(JSContext *cx, jsval val)
for(i=0; i<p->set->sock_count; i++) {
if(p->set->socks[i].sock == INVALID_SOCKET)
continue;
ret++;
FD_SET(p->set->socks[i].sock, fds);
if(p->set->socks[i].sock > sock)
sock = p->set->socks[i].sock;
}
}
else {
sock = p->sock;
if(sock != INVALID_SOCKET)
ret = 1;
FD_SET(p->sock, fds);
}
}
}
} else if(val!=JSVAL_VOID) {
if(JS_ValueToInt32(cx,val,&intval)) {
if (intval != INVALID_SOCKET)
ret = 1;
sock = intval;
FD_SET(sock, fds);
}
}
return ret;
return sock;
}
size_t DLLCALL js_socket_add(JSContext *cx, jsval val, struct pollfd *fds, short events)
BOOL DLLCALL js_socket_isset(JSContext *cx, jsval val, fd_set *fds)
{
js_socket_private_t *p;
JSClass* cl;
SOCKET sock=INVALID_SOCKET;
size_t i;
int32_t intval;
size_t ret = 0;
int intval;
if(JSVAL_IS_OBJECT(val) && (cl=JS_GetClass(cx,JSVAL_TO_OBJECT(val)))!=NULL) {
if(cl->flags&JSCLASS_HAS_PRIVATE) {
......@@ -611,29 +599,41 @@ size_t DLLCALL js_socket_add(JSContext *cx, jsval val, struct pollfd *fds, short
for(i=0; i<p->set->sock_count; i++) {
if(p->set->socks[i].sock == INVALID_SOCKET)
continue;
fds[ret].events = events;
fds[ret++].fd = p->set->socks[i].sock;
if(FD_ISSET(p->set->socks[i].sock, fds))
return TRUE;
}
}
else {
sock = p->sock;
if(sock != INVALID_SOCKET) {
fds[ret].events = events;
fds[ret++].fd = sock;
if (p->sock == INVALID_SOCKET)
return TRUE;
else {
if(FD_ISSET(p->sock, fds))
return TRUE;
}
}
}
}
} else if(val!=JSVAL_VOID) {
if(JS_ValueToInt32(cx,val,&intval)) {
sock = intval;
if(sock != INVALID_SOCKET) {
fds[ret].events = events;
fds[ret++].fd = sock;
}
if(FD_ISSET(intval, fds))
return TRUE;
}
}
return FALSE;
}
void DLLCALL js_timeval(JSContext* cx, jsval val, struct timeval* tv)
{
jsdouble jsd;
if(JSVAL_IS_INT(val))
tv->tv_sec = JSVAL_TO_INT(val);
else if(JSVAL_IS_DOUBLE(val)) {
if(JS_ValueToNumber(cx,val,&jsd)) {
tv->tv_sec = (int)jsd;
tv->tv_usec = (int)(jsd*1000000.0)%1000000;
}
}
return ret;
}
#endif
......@@ -1730,18 +1730,18 @@ js_poll(JSContext *cx, uintN argc, jsval *arglist)
uintN argn;
int result;
jsrefcount rc;
#ifdef _WIN32
#ifdef PREFER_POLL
int timeout = 0;
struct pollfd *fds;
nfds_t nfds;
jsval objval = OBJECT_TO_JSVAL(obj);
#else
size_t i;
SOCKET high=0;
fd_set socket_set;
fd_set* rd_set=NULL;
fd_set* wr_set=NULL;
struct timeval tv = {0, 0};
#else
int timeout = 0;
struct pollfd *fds;
nfds_t nfds;
jsval objval = OBJECT_TO_JSVAL(obj);
#endif
JS_SET_RVAL(cx, arglist, JSVAL_VOID);
......@@ -1760,16 +1760,33 @@ js_poll(JSContext *cx, uintN argc, jsval *arglist)
if(JSVAL_IS_BOOLEAN(argv[argn]))
poll_for_write=JSVAL_TO_BOOLEAN(argv[argn]);
else if(JSVAL_IS_NUMBER(argv[argn])) {
#ifdef _WIN32
js_timeval(cx,argv[argn],&tv);
#else
#ifdef PREFER_POLL
timeout = js_polltimeout(cx, argv[argn]);
#else
js_timeval(cx,argv[argn],&tv);
#endif
}
}
rc=JS_SUSPENDREQUEST(cx);
#ifdef _WIN32
#ifdef PREFER_POLL
if (p->peeked && !poll_for_write) {
result = 1;
}
else {
nfds = js_socket_numsocks(cx, objval);
fds = calloc(nfds, sizeof(*fds));
if (fds == NULL) {
JS_RESUMEREQUEST(cx, rc);
JS_ReportError(cx, "Error allocating %d elements of %lu bytes at %s:%d"
, nfds, sizeof(*fds), getfname(__FILE__), __LINE__);
return JS_FALSE;
}
nfds = js_socket_add(cx, objval, fds, poll_for_write ? POLLOUT : POLLIN);
result = poll(fds, nfds, timeout);
free(fds);
}
#else
FD_ZERO(&socket_set);
if(p->set) {
for(i=0; i<p->set->sock_count; i++) {
......@@ -1791,23 +1808,6 @@ js_poll(JSContext *cx, uintN argc, jsval *arglist)
result = 1;
else
result = select(high+1,rd_set,wr_set,NULL,&tv);
#else
if (p->peeked && !poll_for_write) {
result = 1;
}
else {
nfds = js_socket_numsocks(cx, objval);
fds = calloc(nfds, sizeof(*fds));
if (fds == NULL) {
JS_RESUMEREQUEST(cx, rc);
JS_ReportError(cx, "Error allocating %d elements of %lu bytes at %s:%d"
, nfds, sizeof(*fds), getfname(__FILE__), __LINE__);
return JS_FALSE;
}
nfds = js_socket_add(cx, objval, fds, poll_for_write ? POLLOUT : POLLIN);
result = poll(fds, nfds, timeout);
free(fds);
}
#endif
p->last_error=ERROR_VALUE;
......
......@@ -1870,9 +1870,14 @@ void input_thread(void *arg)
ulong total_pkts=0;
sbbs_t* sbbs = (sbbs_t*) arg;
SOCKET sock;
#ifndef _WIN32
#ifdef PREFER_POLL
struct pollfd fds[2];
int nfds;
#else
fd_set socket_set;
struct timeval tv;
SOCKET high_socket;
SOCKET sock;
#endif
SetThreadName("sbbs/termInput");
......@@ -1890,7 +1895,7 @@ void input_thread(void *arg)
if(pthread_mutex_lock(&sbbs->input_thread_mutex)!=0)
sbbs->errormsg(WHERE,ERR_LOCK,"input_thread_mutex",0);
#ifdef _WIN32
#ifdef _WIN32 // No spy sockets
if (!socket_readable(sbbs->client_socket, 1000)) {
if(pthread_mutex_unlock(&sbbs->input_thread_mutex)!=0)
sbbs->errormsg(WHERE,ERR_UNLOCK,"input_thread_mutex",0);
......@@ -1898,6 +1903,7 @@ void input_thread(void *arg)
continue; /* to allow other threads to lock the input_thread_mutex */
}
#else
#ifdef PREFER_POLL
fds[0].fd = sbbs->client_socket;
fds[0].events = POLLIN;
fds[0].revents = 0;
......@@ -1915,6 +1921,9 @@ void input_thread(void *arg)
YIELD(); /* This kludge is necessary on some Linux distros */
continue; /* to allow other threads to lock the input_thread_mutex */
}
#else
#error Spy sockets without poll() was removed in commit 3971ef4dcc3db19f400a648b6110718e56a64cf3
#endif
#endif
if(sbbs->client_socket==INVALID_SOCKET) {
......@@ -1934,12 +1943,13 @@ void input_thread(void *arg)
* ------------