[erlang-questions] gen_tcp not correctly handling half duplex (shutdown) sockets?
Scott R Parish
srp@REDACTED
Tue Dec 18 19:28:38 CET 2007
Its not clear to me if i'm doing something wrong, or if gen_tcp isn't
correctly handling half duplex sockets. As a refresher, half duplex
sockets are created when shutdown(2) is called on a socket to close one
direction:
http://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-2.html#ss2.6
My erlang code is acting as follows:
maple% erl
Erlang (BEAM) emulator version 5.5.5 [source] [async-threads:0] [hipe]
[kernel-poll:false]
Eshell V5.5.5 (abort with ^G)
1> Opts = [binary, {packet, raw}, {active, false}].
[binary,{packet,raw},{active,false}]
2> {ok, LS} = gen_tcp:listen(6000, Opts).
{ok,#Port<0.70>}
3> {ok, S1} = gen_tcp:connect("localhost", 6000, Opts).
{ok,#Port<0.72>}
4> {ok, S2} = gen_tcp:accept(LS).
{ok,#Port<0.73>}
5> ok = gen_tcp:shutdown(S1, write).
ok
6> gen_tcp:recv(S2, 0).
{error,closed}
7> gen_tcp:recv(S2, 0).
{error,ebadf}
8> gen_tcp:recv(S2, 0).
{error,ebadf}
After "6>", sending also refuses to work:
...
7> gen_tcp:send(S2, <<"blah">>).
{error,ebadf}
Its like erlang is thinking that the whole socket got closed, instead of
just one direction, and close()ed it.
For comparison, some c code i wrote works as i'd expect:
<<<START s.c>>>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>
int main(int argc, char **argv) {
int s[2];
int r;
if (0 != socketpair(AF_UNIX, SOCK_STREAM, 0, s)) {
fprintf(stderr, "socketpair error: %s\n", strerror(errno));
return 1;
}
if (0 != shutdown(s[0], SHUT_WR)) {
fprintf(stderr, "shutdown: %s\n", strerror(errno));
return 2;
}
char buf[1024];
r = recv(s[1], buf, 1024, 0);
fprintf(stderr, "recv 1 => %d\n", r);
if (0 > r) {
fprintf(stderr, "recv 1: %s\n", strerror(errno));
return 3;
}
r = recv(s[1], buf, 1024, 0);
fprintf(stderr, "recv 1 => %d\n", r);
if (0 > r) {
fprintf(stderr, "recv 1: %s\n", strerror(errno));
return 3;
}
if (5 != send(s[1], "blah", 5, 0)) {
fprintf(stderr, "send: %s\n", strerror(errno));
return 2;
}
r = recv(s[0], buf, 1024, 0);
fprintf(stderr, "recv 2 => %d\n", r);
if (0 > r) {
fprintf(stderr, "recv 2: %s\n", strerror(errno));
return 3;
}
printf("got: %s\n", buf);
return 0;
}
<<<END s.c>>>
maple% make s
cc s.c -o s
maple% ./s; echo $?
recv 1 => 0
recv 1 => 0
recv 2 => 5
got: blah
0
Thanks for any help!
sRp
More information about the erlang-questions
mailing list