[mosh-devel] [PATCH 1/2] workaround for systems not providing pselect

Jérémie Courrèges-Anglas jca at wxcvbn.org
Tue Mar 12 06:46:42 EDT 2013


using a mix of good old select and sigprocmask
---
 configure.ac      |  2 +-
 src/util/select.h | 21 +++++++++++++++++++--
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/configure.ac b/configure.ac
index 8220621..a3d3419 100644
--- a/configure.ac
+++ b/configure.ac
@@ -195,7 +195,7 @@ AC_TYPE_UINTPTR_T
 # Checks for library functions.
 AC_FUNC_FORK
 AC_FUNC_MBRTOWC
-AC_CHECK_FUNCS([gettimeofday setrlimit inet_ntoa iswprint memchr memset nl_langinfo posix_memalign setenv setlocale sigaction socket strchr strdup strncasecmp strtok strerror strtol wcwidth cfmakeraw])
+AC_CHECK_FUNCS([gettimeofday setrlimit inet_ntoa iswprint memchr memset nl_langinfo posix_memalign setenv setlocale sigaction socket strchr strdup strncasecmp strtok strerror strtol wcwidth cfmakeraw pselect])
 
 AC_SEARCH_LIBS([clock_gettime], [rt], [AC_DEFINE([HAVE_CLOCK_GETTIME], [1], [Define if clock_gettime is available.])])
 
diff --git a/src/util/select.h b/src/util/select.h
index dc06716..6d9922f 100644
--- a/src/util/select.h
+++ b/src/util/select.h
@@ -118,6 +118,7 @@ public:
     fatal_assert( 0 == sigaction( signum, &sa, NULL ) );
   }
 
+  /* timeout unit: milliseconds; negative timeout means wait forever */
   int select( int timeout )
   {
     memcpy( &read_fds,  &all_fds, sizeof( read_fds  ) );
@@ -125,18 +126,34 @@ public:
     clear_got_signal();
     got_any_signal = 0;
 
+#ifdef HAVE_PSELECT
     struct timespec ts;
     struct timespec *tsp = NULL;
 
     if ( timeout >= 0 ) {
-      // timeout in milliseconds
       ts.tv_sec  = timeout / 1000;
       ts.tv_nsec = 1000000 * (long( timeout ) % 1000);
       tsp = &ts;
     }
-    // negative timeout means wait forever
 
     int ret = ::pselect( max_fd + 1, &read_fds, NULL, &error_fds, tsp, &empty_sigset );
+#else
+    struct timeval tv;
+    struct timeval *tvp = NULL;
+    sigset_t old_sigset;
+
+    if ( timeout >= 0 ) {
+      tv.tv_sec  = timeout / 1000;
+      tv.tv_usec = 1000 * (long( timeout ) % 1000);
+      tvp = &tv;
+    }
+
+    int ret = sigprocmask( SIG_SETMASK, &empty_sigset, &old_sigset );
+    if ( ret != -1 ) {
+      ret = ::select( max_fd + 1, &read_fds, NULL, &error_fds, tvp );
+      sigprocmask( SIG_SETMASK, &old_sigset, NULL );
+    }
+#endif
 
     if ( ( ret == -1 ) && ( errno == EINTR ) ) {
       /* The user should process events as usual. */
-- 
1.8.1.2




More information about the mosh-devel mailing list