interference of FFI with poll(3)?
Nick Rudnick <[email protected]> Sat, 28 Apr 2012 12:29:43 +0200
| Newsgroups | gmane.comp.lang.haskell.ffi |
|---|---|
| Message-ID | <CA+XUKchDgmVJKXYN-jao9RZ_nc-hT=9eoH-ta4huOGo20WYVBQ@mail.gmail.com> |
--===============1784668053776296429==
Content-Type: multipart/alternative; boundary=e89a8f3ba551ff8f9e04bebab243
--e89a8f3ba551ff8f9e04bebab243
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
--e89a8f3ba551ff8f9e04bebab243
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: quoted-printable
Dear all,<div><br></div><div>after noticing problems with libssh2, and tryi=
ng 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 ser=
ver and a raw C libssh2 (for comparison) with debug messaging, I with suppo=
rt 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>=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->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><font face=3D"'courier new', monospace">LIBSSH2_API =
void libssh2_test(void){<br>=A0 struct sockaddr_in sin;<br>=A0 LIBSSH2_SESS=
ION *session;<br>=A0 const char *fingerprint;<br>=A0 LIBSSH2_CHANNEL *chann=
el;<br>
=A0 const unsigned long hostaddr=3D htonl(0x7F000001);<br>=A0 const char *u=
sername=3D "i";<br>=A0 const char *keyfile1=3D"/home/i/.ssh/=
id_rsa.pub";<br>=A0 const char *keyfile2=3D"/home/i/.ssh/id_rsa&q=
uot;;<br>=A0 const char *password=3D "D0r1nha23";<br>
=A0 int got=3D 0;<br>=A0 int sock=3D socket(AF_INET, SOCK_STREAM, 0);<br>=
=A0 sin.sin_family=3D AF_INET;<br>=A0 sin.sin_port=3D htons(22);<br>=A0 sin=
.sin_addr.s_addr=3D hostaddr;<br>=A0 if(connect( sock, (struct sockaddr*)(&=
amp;sin), sizeof(struct sockaddr_in)<br>
=A0 =A0 =A0 =A0 =A0 =A0 ) !=3D 0 ) {<br>=A0 =A0 fprintf(stderr, "faile=
d to connect!\n");<br>=A0 =A0 return;<br>=A0 }<br>=A0 session=3D libss=
h2_session_init();<br>=A0 libssh2_trace(session,~0);<br>=A0 if(libssh2_sess=
ion_handshake(session, sock)) {<br>
=A0 =A0 _libssh2_debug(session, LIBSSH2_TRACE_TRANS<br>=A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 , "Failure establishing SSH session" );<br>=A0 =
=A0 return;<br>=A0 }<br>=A0 fingerprint=3D libssh2_hostkey_hash(session, LI=
BSSH2_HOSTKEY_HASH_SHA1);<br>=A0 libssh2_userauth_list(session, username, s=
trlen(username)); // ??<br>
=A0 if(libssh2_userauth_publickey_fromfile( session<br>=A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 , username<br>=
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 , keyfile1<br>=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 , keyfile2<br>=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 , password )) {<br>
=A0 =A0 _libssh2_debug(session, LIBSSH2_TRACE_TRANS<br>=A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 , "\tAuthentication by public key failed!" );<br>=
=A0 =A0 return;<br>=A0 } else {<br>=A0 =A0 _libssh2_debug( session, LIBSSH2=
_TRACE_TRANS<br>=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 , "\tAuthenticatio=
n by public key succeeded." );<br>
=A0 =A0 if(!(channel=3D libssh2_channel_open_session(session))) {<br>=A0 =
=A0 =A0 _libssh2_debug( session, LIBSSH2_TRACE_TRANS<br>=A0 =A0 =A0 =A0 =A0=
=A0 =A0 =A0 =A0 =A0 , "Unable to open a session" );<br>=A0 =A0 =
=A0 return;<br>=A0 =A0 } else {<br>=A0 =A0 =A0 libssh2_channel_setenv(chann=
el, "FOO", "bar");<br>
=A0 =A0 =A0 if(libssh2_channel_request_pty(channel, "vanilla")) {=
<br>=A0 =A0 =A0 =A0 _libssh2_debug( session, LIBSSH2_TRACE_TRANS<br>=A0 =A0=
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 , "Failed requesting pty" );=
<br>=A0 =A0 =A0 } else {<br>=A0 =A0 =A0 =A0 if(libssh2_channel_shell(channe=
l)) {<br>
=A0 =A0 =A0 =A0 =A0 _libssh2_debug( session, LIBSSH2_TRACE_TRANS<br>=A0 =A0=
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 , "Unable to request shell on=
allocated pty" );<br>=A0 =A0 =A0 =A0 } else {<br>=A0 =A0 =A0 =A0 =A0 =
if(channel){<br>=A0 =A0 =A0 =A0 =A0 =A0 libssh2_channel_free(channel);<br>
=A0 =A0 =A0 =A0 =A0 =A0 channel=3D NULL;<br>=A0 =A0 =A0 =A0 =A0 }<br>=A0 =
=A0 =A0 =A0 }<br>=A0 =A0 =A0 }<br>=A0 =A0 }<br>=A0 }<br>=A0 libssh2_session=
_disconnect( session<br>=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 , "Normal Shutdown, Thank you for playing" );<br>=A0 libssh2=
_session_free(session);<br>
=A0 close(sock);<br>=A0 libssh2_exit();<br>=A0 return;<br>}</font><div><br>=
</div><div>and called it by</div><div><br></div><font face=3D"'courier =
new', monospace">foreign import ccall unsafe "libssh2_test" =
=A0<br>
=A0 libssh2Test:: IO ()</font><div><br></div><div>as well as=A0</div><div><=
br></div><font face=3D"'courier new', monospace">{# context lib=3D&=
quot;ssh2" prefix=3D"libssh2" #}<br>{# fun test as test { } =
-> `()' #}</font><div>
<br></div><div>With both approaches, I still got the same EINTR error, whil=
e 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>
--e89a8f3ba551ff8f9e04bebab243--
--===============1784668053776296429==
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
--===============1784668053776296429==--