<div>Dear all,</div><div><br></div><div>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.</div><div><br></div><div>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(),</div>
<div><br></div><div> rc = poll(sockets, 1, has_timeout?ms_to_next: -1);</div><div><br></div><div>where sockets consists of a single socket, session->socket_fd.</div><div><br></div><div>This is roughly a polling with timeout for the connection – and, with the Haskell FFI, an</div>
<div><br></div><div> error 4 / EINTR / Interrupted system call</div><div><br></div><div>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,</div>
<div><br></div><div>LIBSSH2_API void libssh2_test(void){</div><div> struct sockaddr_in sin;</div><div> LIBSSH2_SESSION *session;</div><div> const char *fingerprint;</div><div> LIBSSH2_CHANNEL *channel;</div><div> const unsigned long hostaddr= htonl(0x7F000001);</div>
<div> const char *username= "i";</div><div> const char *keyfile1="/home/i/.ssh/id_rsa.pub";</div><div> const char *keyfile2="/home/i/.ssh/id_rsa";</div><div> const char *password= "D0r1nha23";</div>
<div> int got= 0;</div><div> int sock= socket(AF_INET, SOCK_STREAM, 0);</div><div> sin.sin_family= AF_INET;</div><div> sin.sin_port= htons(22);</div><div> sin.sin_addr.s_addr= hostaddr;</div><div> if(connect( sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)</div>
<div> ) != 0 ) {</div><div> fprintf(stderr, "failed to connect!\n");</div><div> return;</div><div> }</div><div> session= libssh2_session_init();</div><div> libssh2_trace(session,~0);</div><div>
if(libssh2_session_handshake(session, sock)) {</div><div> _libssh2_debug(session, LIBSSH2_TRACE_TRANS</div><div> , "Failure establishing SSH session" );</div><div> return;</div><div> }</div>
<div> fingerprint= libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);</div><div> libssh2_userauth_list(session, username, strlen(username)); // ??</div><div> if(libssh2_userauth_publickey_fromfile( session</div>
<div> , username</div><div> , keyfile1</div><div> , keyfile2</div><div> , password )) {</div>
<div> _libssh2_debug(session, LIBSSH2_TRACE_TRANS</div><div> , "\tAuthentication by public key failed!" );</div><div> return;</div><div> } else {</div><div> _libssh2_debug( session, LIBSSH2_TRACE_TRANS</div>
<div> , "\tAuthentication by public key succeeded." );</div><div> if(!(channel= libssh2_channel_open_session(session))) {</div><div> _libssh2_debug( session, LIBSSH2_TRACE_TRANS</div><div>
, "Unable to open a session" );</div><div> return;</div><div> } else {</div><div> libssh2_channel_setenv(channel, "FOO", "bar");</div><div> if(libssh2_channel_request_pty(channel, "vanilla")) {</div>
<div> _libssh2_debug( session, LIBSSH2_TRACE_TRANS</div><div> , "Failed requesting pty" );</div><div> } else {</div><div> if(libssh2_channel_shell(channel)) {</div><div> _libssh2_debug( session, LIBSSH2_TRACE_TRANS</div>
<div> , "Unable to request shell on allocated pty" );</div><div> } else {</div><div> if(channel){</div><div> libssh2_channel_free(channel);</div><div> channel= NULL;</div>
<div> }</div><div> }</div><div> }</div><div> }</div><div> }</div><div> libssh2_session_disconnect( session</div><div> , "Normal Shutdown, Thank you for playing" );</div>
<div> libssh2_session_free(session);</div><div> close(sock);</div><div> libssh2_exit();</div><div> return;</div><div>}</div><div><br></div><div>and called it by</div><div><br></div><div>foreign import ccall unsafe "libssh2_test" </div>
<div> libssh2Test:: IO ()</div><div><br></div><div>as well as </div><div><br></div><div>{# context lib="ssh2" prefix="libssh2" #}</div><div>{# fun test as test { } -> `()' #}</div><div><br></div>
<div>With both approaches, I still got the same EINTR error, while coalling libssh2_test() from C works completely flawless.</div><div><br></div><div>Is it possible that an interfering signal comes from the FFI? If yes, is there a workaround?</div>
<div><br></div><div>Grateful for any kind of enlightenment... :-)</div><div><br></div><div>Thanks a lot in advance, Nick</div><div><br></div>