[FFI] interference of FFI with poll(3)?

Edward Z. Yang ezyang at MIT.EDU
Sun Apr 29 06:48:27 CEST 2012


Hello Nick,

The GHC runtime system uses alarm signals for a variety of purposes,
and part of this means that your code needs to properly handle
EINTR.  Please see: http://hackage.haskell.org/trac/ghc/wiki/Commentary/Rts/Signals
for more information.

Cheers,
Edward

Excerpts from Nick Rudnick's message of Sat Apr 28 07:21:30 -0400 2012:
> Dear all,
> 
> after noticing problems with libssh2, and trying to fix this myself, I ran
> into a strange experience which I wish to get an explanation for.
> 
> After compiling an OpenSSH server and a raw C libssh2 (for comparison) with
> debug messaging, I with support of the libssh2 community was able to trace
> the problem back to a call to poll(3) in session.c::_libssh2_wait_socket(),
> 
>    rc = poll(sockets, 1, has_timeout?ms_to_next: -1);
> 
> where sockets consists of a single socket, session->socket_fd.
> 
> This is roughly a polling with timeout for the connection – and, with the
> Haskell FFI, an
> 
>   error 4 / EINTR / Interrupted system call
> 
> is thrown, and I was explained that this probably is caused by another
> signal of the same code unit. Not finding anything, I at the end extended
> libssh2 by a function,
> 
> LIBSSH2_API void libssh2_test(void){
>   struct sockaddr_in sin;
>   LIBSSH2_SESSION *session;
>   const char *fingerprint;
>   LIBSSH2_CHANNEL *channel;
>   const unsigned long hostaddr= htonl(0x7F000001);
>   const char *username= "i";
>   const char *keyfile1="/home/i/.ssh/id_rsa.pub";
>   const char *keyfile2="/home/i/.ssh/id_rsa";
>   const char *password= "D0r1nha23";
>   int got= 0;
>   int sock= socket(AF_INET, SOCK_STREAM, 0);
>   sin.sin_family= AF_INET;
>   sin.sin_port= htons(22);
>   sin.sin_addr.s_addr= hostaddr;
>   if(connect( sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)
>             ) != 0 ) {
>     fprintf(stderr, "failed to connect!\n");
>     return;
>   }
>   session= libssh2_session_init();
>   libssh2_trace(session,~0);
>   if(libssh2_session_handshake(session, sock)) {
>     _libssh2_debug(session, LIBSSH2_TRACE_TRANS
>                   , "Failure establishing SSH session" );
>     return;
>   }
>   fingerprint= libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
>   libssh2_userauth_list(session, username, strlen(username)); // ??
>   if(libssh2_userauth_publickey_fromfile( session
>                                         , username
>                                         , keyfile1
>                                         , keyfile2
>                                         , password )) {
>     _libssh2_debug(session, LIBSSH2_TRACE_TRANS
>                   , "\tAuthentication by public key failed!" );
>     return;
>   } else {
>     _libssh2_debug( session, LIBSSH2_TRACE_TRANS
>                   , "\tAuthentication by public key succeeded." );
>     if(!(channel= libssh2_channel_open_session(session))) {
>       _libssh2_debug( session, LIBSSH2_TRACE_TRANS
>                     , "Unable to open a session" );
>       return;
>     } else {
>       libssh2_channel_setenv(channel, "FOO", "bar");
>       if(libssh2_channel_request_pty(channel, "vanilla")) {
>         _libssh2_debug( session, LIBSSH2_TRACE_TRANS
>                       , "Failed requesting pty" );
>       } else {
>         if(libssh2_channel_shell(channel)) {
>           _libssh2_debug( session, LIBSSH2_TRACE_TRANS
>                         , "Unable to request shell on allocated pty" );
>         } else {
>           if(channel){
>             libssh2_channel_free(channel);
>             channel= NULL;
>           }
>         }
>       }
>     }
>   }
>   libssh2_session_disconnect( session
>                             , "Normal Shutdown, Thank you for playing" );
>   libssh2_session_free(session);
>   close(sock);
>   libssh2_exit();
>   return;
> }
> 
> and called it by
> 
> foreign import ccall unsafe "libssh2_test"
>   libssh2Test:: IO ()
> 
> as well as
> 
> {# context lib="ssh2" prefix="libssh2" #}
> {# fun test as test { } -> `()' #}
> 
> With both approaches, I still got the same EINTR error, while coalling
> libssh2_test() from C works completely flawless.
> 
> Is it possible that an interfering signal comes from the FFI? If yes, is
> there a workaround?
> 
> Grateful for any kind of enlightenment... :-)
> 
> Thanks a lot in advance, Nick



More information about the FFI mailing list