[erlang-questions] gen_tcp not correctly handling half duplex (shutdown) sockets?

Scott R Parish <>
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