1
0
mirror of https://github.com/libssh2/libssh2.git synced 2026-10-24 03:48:58 +03:00

session: drop alloca() use from libssh2_poll()

Use fixed stack buffer when requested 256 sockets or less. Allocate from
heap otherwise.

There is no other `alloca()` user, so drop detecting it via autotools
(CMake never got support for this). Also re-enable a warning option that
was incompatible with autotools's `AC_FUNC_ALLOCA` code.

This patch may reduce performance when polling 257+ sockets (due to
calloc/free), and comes with higher stack use ('256 * sizeof(struct
pollfd)') than before this patch, when using `poll()` (typically on Unix
platforms except Darwin and Interix).

Note: `libssh2_poll()` is deprecated since v1.2.0 (2009-08-10).

Follow-up to 209d06d6c9

Closes #2041
This commit is contained in:
Viktor Szakats
2026-06-11 12:31:40 +02:00
parent 80bfa8a2e3
commit 787e9bfec2
4 changed files with 22 additions and 28 deletions

View File

@@ -631,11 +631,7 @@ AC_DEFUN([CURL_CC_DEBUG_OPTS],
dnl Only gcc 15 or later
if test "$compiler_num" -ge "1500"; then
dnl AC_FUNC_ALLOCA is incompatible with this option. It triggers
dnl detecting macro STACK_DIRECTION (which we do not use here).
dnl autoconf (as of v2.73) puts this macro into libssh2_config.h
dnl indented by tabs.
# CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [leading-whitespace=spaces])
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [leading-whitespace=spaces])
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [trailing-whitespace=any])
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unterminated-string-initialization])
fi

View File

@@ -398,8 +398,6 @@ if test "$ac_cv_func_select" != "yes"; then
])
fi
AC_FUNC_ALLOCA
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST

View File

@@ -52,12 +52,6 @@
/* Define to 1 if using `alloca.c'. */
#undef C_ALLOCA
/* Define to 1 if you have `alloca', as a function or macro. */
#define HAVE_ALLOCA 1
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix). */
#define HAVE_ALLOCA_H 1
/* Define to 1 if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H 1

View File

@@ -47,9 +47,6 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
#include <errno.h>
#include <stdlib.h>
@@ -1519,16 +1516,18 @@ int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout)
unsigned int i, active_fds;
#ifdef HAVE_POLL
LIBSSH2_SESSION *session = NULL;
#ifdef HAVE_ALLOCA
struct pollfd *sockets = alloca(sizeof(struct pollfd) * nfds);
#else
struct pollfd sockets[256];
struct pollfd sockets_stack[256];
struct pollfd *sockets_heap = NULL;
struct pollfd *sockets;
if(nfds > 256) {
sockets = sockets_heap = calloc(nfds, sizeof(struct pollfd));
if(!sockets)
return -1;
}
else
sockets = sockets_stack;
if(nfds > 256)
/* systems without alloca use a fixed-size array, this can be fixed if
we really want to, at least if the compiler is a C99 capable one */
return -1;
#endif /* HAVE_ALLOCA */
/* Setup sockets for polling */
for(i = 0; i < nfds; i++) {
fds[i].revents = 0;
@@ -1556,6 +1555,8 @@ int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout)
break;
default:
if(sockets_heap)
free(sockets_heap);
if(session)
ssh2_err(session, LIBSSH2_ERROR_INVALID_POLL_TYPE,
"Invalid descriptor passed to libssh2_poll()");
@@ -1646,7 +1647,6 @@ int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout)
#if defined(HAVE_POLL) || defined(HAVE_SELECT)
int sysret;
#endif
active_fds = 0;
for(i = 0; i < nfds; i++) {
@@ -1717,8 +1717,8 @@ int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout)
are ready */
timeout_remaining = 0;
}
#ifdef HAVE_POLL
#ifdef HAVE_POLL
{
struct timeval tv_begin, tv_end;
@@ -1768,14 +1768,15 @@ int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout)
}
}
}
#elif defined(HAVE_SELECT)
tv.tv_sec = timeout_remaining / 1000;
#ifdef libssh2_usec_t
tv.tv_usec = (libssh2_usec_t)((timeout_remaining % 1000) * 1000);
#else
tv.tv_usec = (timeout_remaining % 1000) * 1000;
#endif
{
struct timeval tv_begin, tv_end;
@@ -1833,6 +1834,11 @@ int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeout)
* timeout_remaining) is equal to 0 */
} while(timeout_remaining > 0 && !active_fds);
#ifdef HAVE_POLL
if(sockets_heap)
free(sockets_heap);
#endif
return active_fds;
}
#endif /* LIBSSH2_NO_DEPRECATED */