Reduce usage of malloc in select and poll. Fix poll not acceping -1 fds

This commit is contained in:
TuxSH 2018-09-21 13:54:41 +02:00 committed by yellows8
parent fba43b0f10
commit 052fb34397

View File

@ -4,6 +4,7 @@
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <malloc.h> #include <malloc.h>
#include <alloca.h>
#include <sys/iosupport.h> #include <sys/iosupport.h>
#include <sys/select.h> #include <sys/select.h>
@ -24,6 +25,8 @@
#include "services/nifm.h" #include "services/nifm.h"
#include "result.h" #include "result.h"
__attribute__((weak)) size_t __nx_pollfd_sb_max_fds = 64;
int _convert_errno(int bsdErrno); int _convert_errno(int bsdErrno);
__thread int h_errno; __thread int h_errno;
@ -261,6 +264,9 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struc
++numfds; ++numfds;
} }
if(numfds <= __nx_pollfd_sb_max_fds)
pollinfo = (struct pollfd *)alloca(numfds * sizeof(struct pollfd));
else
pollinfo = (struct pollfd *)malloc(numfds * sizeof(struct pollfd)); pollinfo = (struct pollfd *)malloc(numfds * sizeof(struct pollfd));
if(pollinfo == NULL) { if(pollinfo == NULL) {
errno = ENOMEM; errno = ENOMEM;
@ -271,7 +277,11 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struc
if((readfds && FD_ISSET(i, readfds)) if((readfds && FD_ISSET(i, readfds))
|| (writefds && FD_ISSET(i, writefds)) || (writefds && FD_ISSET(i, writefds))
|| (exceptfds && FD_ISSET(i, exceptfds))) { || (exceptfds && FD_ISSET(i, exceptfds))) {
pollinfo[j].fd = i; pollinfo[j].fd = _socketGetFd(i);
if(pollinfo[j].fd == -1) {
rc = -1;
goto cleanup;
}
pollinfo[j].events = 0; pollinfo[j].events = 0;
pollinfo[j].revents = 0; pollinfo[j].revents = 0;
@ -285,14 +295,12 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struc
} }
if(timeout) if(timeout)
rc = poll(pollinfo, numfds, timeout->tv_sec*1000 + timeout->tv_usec/1000); rc = _socketParseBsdResult(NULL, bsdPoll(pollinfo, numfds, timeout->tv_sec*1000 + timeout->tv_usec/1000));
else else
rc = poll(pollinfo, numfds, -1); rc = _socketParseBsdResult(NULL, bsdPoll(pollinfo, numfds, -1));
if(rc < 0) { if(rc < 0)
free(pollinfo); goto cleanup;
return rc;
}
for(i = 0, j = 0, rc = 0; i < nfds; ++i) { for(i = 0, j = 0, rc = 0; i < nfds; ++i) {
found = 0; found = 0;
@ -328,8 +336,9 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struc
} }
} }
cleanup:
if(numfds > __nx_pollfd_sb_max_fds)
free(pollinfo); free(pollinfo);
return rc; return rc;
} }
@ -343,6 +352,9 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout) {
return -1; return -1;
} }
if(nfds <= __nx_pollfd_sb_max_fds)
fds2 = (struct pollfd *)alloca(nfds * sizeof(struct pollfd));
else
fds2 = (struct pollfd *)malloc(nfds * sizeof(struct pollfd)); fds2 = (struct pollfd *)malloc(nfds * sizeof(struct pollfd));
if(fds2 == NULL) { if(fds2 == NULL) {
errno = ENOMEM; errno = ENOMEM;
@ -352,12 +364,16 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout) {
for(nfds_t i = 0; i < nfds; i++) { for(nfds_t i = 0; i < nfds; i++) {
fds2[i].events = fds[i].events; fds2[i].events = fds[i].events;
fds2[i].revents = fds[i].revents; fds2[i].revents = fds[i].revents;
if(fds[i].fd < 0) {
fds2[i].fd = -1;
} else {
fds2[i].fd = _socketGetFd(fds[i].fd); fds2[i].fd = _socketGetFd(fds[i].fd);
if(fds2[i].fd == -1) { if(fds2[i].fd == -1) {
ret = -1; ret = -1;
break; break;
} }
} }
}
if(ret != -1) if(ret != -1)
ret = _socketParseBsdResult(NULL, bsdPoll(fds2, nfds, timeout)); ret = _socketParseBsdResult(NULL, bsdPoll(fds2, nfds, timeout));
@ -368,6 +384,7 @@ int poll(struct pollfd *fds, nfds_t nfds, int timeout) {
} }
} }
if(nfds > __nx_pollfd_sb_max_fds)
free(fds2); free(fds2);
return ret; return ret;
} }