interference of FFI with poll(3)?

Nick Rudnick <[email protected]> Sat, 28 Apr 2012 13:21:30 +0200
Newsgroups gmane.comp.lang.haskell.ffi
Message-ID <CA+XUKcgOPaO4BF0RHaqJGCv_tao83Qdz1Gg7eMfyH1Dm3=d6-A@mail.gmail.com>
--===============3290123838574762873==
Content-Type: multipart/alternative; boundary=90e6ba61456a3145d704bebb6c69

--90e6ba61456a3145d704bebb6c69
Content-Type: text/plain; charset=windows-1252
Content-Transfer-Encoding: quoted-printable

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 =3D 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 =96 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=3D htonl(0x7F000001);
  const char *username=3D "i";
  const char *keyfile1=3D"/home/i/.ssh/id_rsa.pub";
  const char *keyfile2=3D"/home/i/.ssh/id_rsa";
  const char *password=3D "D0r1nha23";
  int got=3D 0;
  int sock=3D socket(AF_INET, SOCK_STREAM, 0);
  sin.sin_family=3D AF_INET;
  sin.sin_port=3D htons(22);
  sin.sin_addr.s_addr=3D hostaddr;
  if(connect( sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)
            ) !=3D 0 ) {
    fprintf(stderr, "failed to connect!\n");
    return;
  }
  session=3D 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=3D 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=3D 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=3D 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=3D"ssh2" prefix=3D"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

--90e6ba61456a3145d704bebb6c69
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: quoted-printable

<div>Dear all,</div><div><br></div><div>after noticing problems with libssh=
2, and trying to fix this myself, I ran into a strange experience which I w=
ish 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 t=
o a call to poll(3) in session.c::_libssh2_wait_socket(),</div>
<div><br></div><div>=A0 =A0rc =3D poll(sockets, 1, has_timeout?ms_to_next: =
-1);</div><div><br></div><div>where sockets consists of a single socket, se=
ssion-&gt;socket_fd.</div><div><br></div><div>This is roughly a polling wit=
h timeout for the connection =96 and, with the Haskell FFI, an</div>
<div><br></div><div>=A0 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 en=
d extended libssh2 by a function,</div>
<div><br></div><div>LIBSSH2_API void libssh2_test(void){</div><div>=A0 stru=
ct sockaddr_in sin;</div><div>=A0 LIBSSH2_SESSION *session;</div><div>=A0 c=
onst char *fingerprint;</div><div>=A0 LIBSSH2_CHANNEL *channel;</div><div>=
=A0 const unsigned long hostaddr=3D htonl(0x7F000001);</div>
<div>=A0 const char *username=3D &quot;i&quot;;</div><div>=A0 const char *k=
eyfile1=3D&quot;/home/i/.ssh/id_rsa.pub&quot;;</div><div>=A0 const char *ke=
yfile2=3D&quot;/home/i/.ssh/id_rsa&quot;;</div><div>=A0 const char *passwor=
d=3D &quot;D0r1nha23&quot;;</div>
<div>=A0 int got=3D 0;</div><div>=A0 int sock=3D socket(AF_INET, SOCK_STREA=
M, 0);</div><div>=A0 sin.sin_family=3D AF_INET;</div><div>=A0 sin.sin_port=
=3D htons(22);</div><div>=A0 sin.sin_addr.s_addr=3D hostaddr;</div><div>=A0=
 if(connect( sock, (struct sockaddr*)(&amp;sin), sizeof(struct sockaddr_in)=
</div>
<div>=A0 =A0 =A0 =A0 =A0 =A0 ) !=3D 0 ) {</div><div>=A0 =A0 fprintf(stderr,=
 &quot;failed to connect!\n&quot;);</div><div>=A0 =A0 return;</div><div>=A0=
 }</div><div>=A0 session=3D libssh2_session_init();</div><div>=A0 libssh2_t=
race(session,~0);</div><div>
=A0 if(libssh2_session_handshake(session, sock)) {</div><div>=A0 =A0 _libss=
h2_debug(session, LIBSSH2_TRACE_TRANS</div><div>=A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 , &quot;Failure establishing SSH session&quot; );</div><div>=A0 =
=A0 return;</div><div>=A0 }</div>
<div>=A0 fingerprint=3D libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_=
SHA1);</div><div>=A0 libssh2_userauth_list(session, username, strlen(userna=
me)); // ??</div><div>=A0 if(libssh2_userauth_publickey_fromfile( session</=
div>
<div>=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 , username</div><div>=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 , keyfile1</div><div>=A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 , keyfi=
le2</div><div>=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 , password )) {</div>
<div>=A0 =A0 _libssh2_debug(session, LIBSSH2_TRACE_TRANS</div><div>=A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 , &quot;\tAuthentication by public key failed!&=
quot; );</div><div>=A0 =A0 return;</div><div>=A0 } else {</div><div>=A0 =A0=
 _libssh2_debug( session, LIBSSH2_TRACE_TRANS</div>
<div>=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 , &quot;\tAuthentication by public=
 key succeeded.&quot; );</div><div>=A0 =A0 if(!(channel=3D libssh2_channel_=
open_session(session))) {</div><div>=A0 =A0 =A0 _libssh2_debug( session, LI=
BSSH2_TRACE_TRANS</div><div>
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 , &quot;Unable to open a session&qu=
ot; );</div><div>=A0 =A0 =A0 return;</div><div>=A0 =A0 } else {</div><div>=
=A0 =A0 =A0 libssh2_channel_setenv(channel, &quot;FOO&quot;, &quot;bar&quot=
;);</div><div>=A0 =A0 =A0 if(libssh2_channel_request_pty(channel, &quot;van=
illa&quot;)) {</div>
<div>=A0 =A0 =A0 =A0 _libssh2_debug( session, LIBSSH2_TRACE_TRANS</div><div=
>=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 , &quot;Failed requesting pty&=
quot; );</div><div>=A0 =A0 =A0 } else {</div><div>=A0 =A0 =A0 =A0 if(libssh=
2_channel_shell(channel)) {</div><div>=A0 =A0 =A0 =A0 =A0 _libssh2_debug( s=
ession, LIBSSH2_TRACE_TRANS</div>
<div>=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 , &quot;Unable to requ=
est shell on allocated pty&quot; );</div><div>=A0 =A0 =A0 =A0 } else {</div=
><div>=A0 =A0 =A0 =A0 =A0 if(channel){</div><div>=A0 =A0 =A0 =A0 =A0 =A0 li=
bssh2_channel_free(channel);</div><div>=A0 =A0 =A0 =A0 =A0 =A0 channel=3D N=
ULL;</div>
<div>=A0 =A0 =A0 =A0 =A0 }</div><div>=A0 =A0 =A0 =A0 }</div><div>=A0 =A0 =
=A0 }</div><div>=A0 =A0 }</div><div>=A0 }</div><div>=A0 libssh2_session_dis=
connect( session</div><div>=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 , &quot;Normal Shutdown, Thank you for playing&quot; );</div>
<div>=A0 libssh2_session_free(session);</div><div>=A0 close(sock);</div><di=
v>=A0 libssh2_exit();</div><div>=A0 return;</div><div>}</div><div><br></div=
><div>and called it by</div><div><br></div><div>foreign import ccall unsafe=
 &quot;libssh2_test&quot; =A0</div>
<div>=A0 libssh2Test:: IO ()</div><div><br></div><div>as well as=A0</div><d=
iv><br></div><div>{# context lib=3D&quot;ssh2&quot; prefix=3D&quot;libssh2&=
quot; #}</div><div>{# fun test as test { } -&gt; `()&#39; #}</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 th=
ere 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>

--90e6ba61456a3145d704bebb6c69--


--===============3290123838574762873==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
FFI mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/ffi

--===============3290123838574762873==--