From: Tulio A M Mendes Date: Sun, 19 Apr 2026 21:30:12 +0000 (-0300) Subject: fix select() timeout conversion — was passing raw pointer as kernel timeout X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=d1c7dc7411f0de2e228526b73f83ed2f0a1df5e8;p=AdrOS.git fix select() timeout conversion — was passing raw pointer as kernel timeout The select() wrapper in both newlib/posix_stubs.c and ulibc/unistd.c was casting the struct timeval* pointer directly to int and passing it as the 5th syscall argument. The kernel expects an int32_t timeout: -1 = infinite wait, 0 = poll (return immediately), >0 = ticks. When bash calls select() with timeout=NULL (infinite wait), the raw pointer value was interpreted as a large positive number (poll with timeout), not as -1 (infinite). Worse, on some code paths the pointer could be 0 (NULL), which the kernel treats as timeout=0 (poll only), causing select() to return 0 immediately with no fds ready — which bash interprets as EOF on stdin, causing it to exit immediately. Fix: convert struct timeval to int32_t ticks before passing to the kernel. NULL timeout → -1 (infinite). tv_sec=0, tv_usec=0 → 0 (poll). Otherwise convert ms → ticks (TIMER_HZ=100, 10ms/tick). --- diff --git a/newlib/libgloss/adros/posix_stubs.c b/newlib/libgloss/adros/posix_stubs.c index db32cadd..108e8260 100644 --- a/newlib/libgloss/adros/posix_stubs.c +++ b/newlib/libgloss/adros/posix_stubs.c @@ -451,8 +451,21 @@ int ioctl(int fd, unsigned long request, ...) { int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { + /* Kernel expects int32_t timeout: -1 = infinite, 0 = poll, >0 = ticks. + * TIMER_HZ = 100, so 1 tick = 10 ms. */ + int32_t tmo = -1; /* default: infinite wait */ + if (timeout) { + if (timeout->tv_sec == 0 && timeout->tv_usec == 0) { + tmo = 0; /* poll only */ + } else { + uint32_t ms = (uint32_t)timeout->tv_sec * 1000 + + (uint32_t)timeout->tv_usec / 1000; + tmo = (int32_t)(ms / 10); /* ms → ticks (10 ms/tick) */ + if (tmo < 1) tmo = 1; + } + } return _check(_sc5(SYS_SELECT, nfds, (int)readfds, (int)writefds, - (int)exceptfds, (int)timeout)); + (int)exceptfds, (int)tmo)); } int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, diff --git a/user/ulibc/src/unistd.c b/user/ulibc/src/unistd.c index 748b78a4..5993e2c8 100644 --- a/user/ulibc/src/unistd.c +++ b/user/ulibc/src/unistd.c @@ -335,8 +335,21 @@ void* sbrk(int increment) { int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout) { + /* Kernel expects int32_t timeout: -1 = infinite, 0 = poll, >0 = ticks. + * TIMER_HZ = 100, so 1 tick = 10 ms. */ + int32_t tmo = -1; + if (timeout) { + if (timeout->tv_sec == 0 && timeout->tv_usec == 0) { + tmo = 0; + } else { + uint32_t ms = (uint32_t)timeout->tv_sec * 1000 + + (uint32_t)timeout->tv_usec / 1000; + tmo = (int32_t)(ms / 10); + if (tmo < 1) tmo = 1; + } + } return __syscall_ret(_syscall5(SYS_SELECT, nfds, (int)readfds, (int)writefds, - (int)exceptfds, (int)timeout)); + (int)exceptfds, (int)tmo)); } int fcntl(int fd, int cmd, ...) {