* Serious bug in the OCaml FFI?
2007-05-05 13:53 ` Mac OSX getsocketpair/getsockname and IPv6 Joel Reymont
@ 2007-05-05 14:13 ` Joel Reymont
2007-05-05 14:56 ` [Caml-list] " Olivier Andrieu
2007-05-05 14:31 ` Mac OSX getsocketpair/getsockname and IPv6 Joel Reymont
2007-05-05 14:46 ` Mac OSX getsocketpair/getsockname and IPv6 Joel Reymont
2 siblings, 1 reply; 13+ messages in thread
From: Joel Reymont @ 2007-05-05 14:13 UTC (permalink / raw)
To: OCaml List
I'm using 32-bit Mac OSX 10.4.9 Intel.
I inserted a print-out into my version of socketpair.c [1] and ran my
OCaml test script
#use "topfind";;
#require "unix";;
let x, y = Unix.socketpair Unix.PF_UNIX Unix.SOCK_STREAM 0;;
Unix.getpeername y;;
which resulted in
unix_socketpair: domain = 1, type = 1, proto = 0
Exception: Unix.Unix_error (Unix.EAFNOSUPPORT, "", "").
Back at the toplevel
# (Obj.magic Unix.PF_UNIX:int);;
- : int = 0
# (Obj.magic Unix.SOCK_STREAM:int);;
- : int = 0
Now, how exactly does 0 become 1 here? I have no idea but there are
two tables defined in otherlibs/unix/socket.c:
int socket_domain_table[] = {
PF_UNIX, PF_INET,
#if defined(HAS_IPV6)
PF_INET6
#elif defined(PF_UNDEF)
PF_UNDEF
#else
0
#endif
};
int socket_type_table[] = {
SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_SEQPACKET
};
As you can see, instead of calling socketpair with PF_UNIX and
SOCK_STREAM), Ocaml is calling it with PF_INET6 and SOCK_DGRAM instead.
This is obviously a major problem. Any suggestions on what may be
causing it and how to fix it?
Thanks, Joel
[1] otherlibs/unix/socketpair.c
CAMLprim value unix_socketpair(value domain, value type, value proto)
{
int sv[2];
value res;
printf("unix_socketpair: domain = %d, type = %d, proto = %d\n",
socket_domain_table[Int_val(domain)],
socket_type_table[Int_val(type)],
Int_val(proto));
if (socketpair(socket_domain_table[Int_val(domain)],
socket_type_table[Int_val(type)],
Int_val(proto), sv) == -1)
uerror("socketpair", Nothing);
res = alloc_small(2, 0);
Field(res,0) = Val_int(sv[0]);
Field(res,1) = Val_int(sv[1]);
return res;
}
--
http://wagerlabs.com/
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Caml-list] Serious bug in the OCaml FFI?
2007-05-05 14:13 ` Serious bug in the OCaml FFI? Joel Reymont
@ 2007-05-05 14:56 ` Olivier Andrieu
2007-05-05 15:24 ` Joel Reymont
0 siblings, 1 reply; 13+ messages in thread
From: Olivier Andrieu @ 2007-05-05 14:56 UTC (permalink / raw)
To: Joel Reymont; +Cc: OCaml List
On 5/5/07, Joel Reymont <joelr1@gmail.com> wrote:
> I'm using 32-bit Mac OSX 10.4.9 Intel.
>
> I inserted a print-out into my version of socketpair.c [1] and ran my
> OCaml test script
>
> #use "topfind";;
> #require "unix";;
> let x, y = Unix.socketpair Unix.PF_UNIX Unix.SOCK_STREAM 0;;
> Unix.getpeername y;;
>
> which resulted in
>
> unix_socketpair: domain = 1, type = 1, proto = 0
> Exception: Unix.Unix_error (Unix.EAFNOSUPPORT, "", "").
>
> Back at the toplevel
>
> # (Obj.magic Unix.PF_UNIX:int);;
> - : int = 0
>
> # (Obj.magic Unix.SOCK_STREAM:int);;
> - : int = 0
>
> Now, how exactly does 0 become 1 here?
It doesn't, your printf prints the value of the C constants PF_UNIX
and SOCK_STREAM, which apparently is 1.
--
Olivier
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Mac OSX getsocketpair/getsockname and IPv6
2007-05-05 13:53 ` Mac OSX getsocketpair/getsockname and IPv6 Joel Reymont
2007-05-05 14:13 ` Serious bug in the OCaml FFI? Joel Reymont
@ 2007-05-05 14:31 ` Joel Reymont
2007-05-05 15:16 ` Solved! (was Re: Mac OSX getsocketpair/getsockname and IPv6) Joel Reymont
2007-05-05 14:46 ` Mac OSX getsocketpair/getsockname and IPv6 Joel Reymont
2 siblings, 1 reply; 13+ messages in thread
From: Joel Reymont @ 2007-05-05 14:31 UTC (permalink / raw)
To: OCaml List
There are no bugs in the OCaml FFI.
socketpair.c:
printf("unix_socketpair: domain = %d/%d/%d, type = %d/%d/%d, proto
= %d\n",
PF_UNIX,
Int_val(domain),
socket_domain_table[Int_val(domain)],
SOCK_STREAM,
Int_val(type),
socket_type_table[Int_val(type)],
Int_val(proto));
Running the test
#use "topfind";;
#require "unix";;
let x, y = Unix.socketpair Unix.PF_UNIX Unix.SOCK_STREAM 0;;
Unix.getpeername y;;
produces
unix_socketpair: domain = 1/0/1, type = 1/0/1, proto = 0
Exception: Unix.Unix_error (Unix.EAFNOSUPPORT, "", "").
So we _are_ passing the proper values and they become proper values
as well.
The problem must be somewhere else, possibly in getsockbyname.c.
Joel
--
http://wagerlabs.com/
^ permalink raw reply [flat|nested] 13+ messages in thread
* Solved! (was Re: Mac OSX getsocketpair/getsockname and IPv6)
2007-05-05 14:31 ` Mac OSX getsocketpair/getsockname and IPv6 Joel Reymont
@ 2007-05-05 15:16 ` Joel Reymont
2007-05-06 10:05 ` [Caml-list] " Gerd Stolpmann
2007-05-28 17:08 ` Paul Snively
0 siblings, 2 replies; 13+ messages in thread
From: Joel Reymont @ 2007-05-05 15:16 UTC (permalink / raw)
To: OCaml List; +Cc: Gerd Stolpmann
The culprit is in alloc_sockaddr [1].
adr->s_gen.sa_family is 0 which stands for AF_UNSPEC in my /usr/
include/sys/socket.h.
alloc_sockaddr does not handle this family type and throws EAFNOSUPPORT.
I'm inclined to think that ocamlnet should be fixed and not the OCaml
library, although it would be helpful if an error different from
EAFNOSUPPORT was used.
I would have been most helpful to have a stack trace on exception as
this would have allowed me to narrow down the source of the problem
in no time rather than going spelunking through ocamlnet and OCaml
networking libraries.
Thanks, Joel
[1] otherlibs/unix/socketaddr.c
value alloc_sockaddr(union sock_addr_union * adr /*in*/,
socklen_param_type adr_len, int close_on_error)
{
value res;
switch(adr->s_gen.sa_family) {
#ifndef _WIN32
case AF_UNIX:
{ value n = copy_string(adr->s_unix.sun_path);
Begin_root (n);
res = alloc_small(1, 0);
Field(res,0) = n;
End_roots();
break;
}
#endif
case AF_INET:
{ value a = alloc_inet_addr(&adr->s_inet.sin_addr);
Begin_root (a);
res = alloc_small(2, 1);
Field(res,0) = a;
Field(res,1) = Val_int(ntohs(adr->s_inet.sin_port));
End_roots();
break;
}
#ifdef HAS_IPV6
case AF_INET6:
{ value a = alloc_inet6_addr(&adr->s_inet6.sin6_addr);
Begin_root (a);
res = alloc_small(2, 1);
Field(res,0) = a;
Field(res,1) = Val_int(ntohs(adr->s_inet6.sin6_port));
End_roots();
break;
}
#endif
default:
if (close_on_error != -1) close (close_on_error);
unix_error(EAFNOSUPPORT, "", Nothing);
}
return res;
}
--
http://wagerlabs.com/
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Caml-list] Solved! (was Re: Mac OSX getsocketpair/getsockname and IPv6)
2007-05-05 15:16 ` Solved! (was Re: Mac OSX getsocketpair/getsockname and IPv6) Joel Reymont
@ 2007-05-06 10:05 ` Gerd Stolpmann
2007-05-28 17:08 ` Paul Snively
1 sibling, 0 replies; 13+ messages in thread
From: Gerd Stolpmann @ 2007-05-06 10:05 UTC (permalink / raw)
To: Joel Reymont; +Cc: OCaml List
Am Samstag, den 05.05.2007, 16:16 +0100 schrieb Joel Reymont:
> The culprit is in alloc_sockaddr [1].
>
> adr->s_gen.sa_family is 0 which stands for AF_UNSPEC in my /usr/
> include/sys/socket.h.
>
> alloc_sockaddr does not handle this family type and throws EAFNOSUPPORT.
>
> I'm inclined to think that ocamlnet should be fixed and not the OCaml
> library, although it would be helpful if an error different from
> EAFNOSUPPORT was used.
Yes, this is true, EAFNOSUPPORT is misleading because it means that the
whole address family is not supported. A better code would be EOPNOTSUPP
which is generally used when a certain socket operation cannot be
performed for the type of socket (and the Single Unix Spec documents it
for getsockname/getpeername). Or Unix.sockaddr is extended by an extra
case for the inaccessible address.
> default:
> if (close_on_error != -1) close (close_on_error);
> unix_error(EAFNOSUPPORT, "", Nothing);
> }
Gerd
--
------------------------------------------------------------
Gerd Stolpmann * Viktoriastr. 45 * 64293 Darmstadt * Germany
gerd@gerd-stolpmann.de http://www.gerd-stolpmann.de
Phone: +49-6151-153855 Fax: +49-6151-997714
------------------------------------------------------------
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Caml-list] Solved! (was Re: Mac OSX getsocketpair/getsockname and IPv6)
2007-05-05 15:16 ` Solved! (was Re: Mac OSX getsocketpair/getsockname and IPv6) Joel Reymont
2007-05-06 10:05 ` [Caml-list] " Gerd Stolpmann
@ 2007-05-28 17:08 ` Paul Snively
1 sibling, 0 replies; 13+ messages in thread
From: Paul Snively @ 2007-05-28 17:08 UTC (permalink / raw)
To: Joel Reymont; +Cc: OCaml List, Gerd Stolpmann
So: if a Mac OS X O'Caml user wanted to solve this, what is the
actual solution? Surely it's not:
case AF_UNSPEC:
case AF_UNIX:
in socketaddr.c?
Many thanks and best regards,
Paul
On May 5, 2007, at 8:16 AM, Joel Reymont wrote:
> The culprit is in alloc_sockaddr [1].
>
> adr->s_gen.sa_family is 0 which stands for AF_UNSPEC in my /usr/
> include/sys/socket.h.
>
> alloc_sockaddr does not handle this family type and throws
> EAFNOSUPPORT.
>
> I'm inclined to think that ocamlnet should be fixed and not the
> OCaml library, although it would be helpful if an error different
> from EAFNOSUPPORT was used.
>
> I would have been most helpful to have a stack trace on exception
> as this would have allowed me to narrow down the source of the
> problem in no time rather than going spelunking through ocamlnet
> and OCaml networking libraries.
>
> Thanks, Joel
>
> [1] otherlibs/unix/socketaddr.c
>
> value alloc_sockaddr(union sock_addr_union * adr /*in*/,
> socklen_param_type adr_len, int close_on_error)
> {
> value res;
> switch(adr->s_gen.sa_family) {
> #ifndef _WIN32
> case AF_UNIX:
> { value n = copy_string(adr->s_unix.sun_path);
> Begin_root (n);
> res = alloc_small(1, 0);
> Field(res,0) = n;
> End_roots();
> break;
> }
> #endif
> case AF_INET:
> { value a = alloc_inet_addr(&adr->s_inet.sin_addr);
> Begin_root (a);
> res = alloc_small(2, 1);
> Field(res,0) = a;
> Field(res,1) = Val_int(ntohs(adr->s_inet.sin_port));
> End_roots();
> break;
> }
> #ifdef HAS_IPV6
> case AF_INET6:
> { value a = alloc_inet6_addr(&adr->s_inet6.sin6_addr);
> Begin_root (a);
> res = alloc_small(2, 1);
> Field(res,0) = a;
> Field(res,1) = Val_int(ntohs(adr->s_inet6.sin6_port));
> End_roots();
> break;
> }
> #endif
> default:
> if (close_on_error != -1) close (close_on_error);
> unix_error(EAFNOSUPPORT, "", Nothing);
> }
> return res;
> }
>
> --
> http://wagerlabs.com/
>
>
>
>
>
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Mac OSX getsocketpair/getsockname and IPv6
2007-05-05 13:53 ` Mac OSX getsocketpair/getsockname and IPv6 Joel Reymont
2007-05-05 14:13 ` Serious bug in the OCaml FFI? Joel Reymont
2007-05-05 14:31 ` Mac OSX getsocketpair/getsockname and IPv6 Joel Reymont
@ 2007-05-05 14:46 ` Joel Reymont
2 siblings, 0 replies; 13+ messages in thread
From: Joel Reymont @ 2007-05-05 14:46 UTC (permalink / raw)
To: OCaml List
As Rich suggested, I ran OCaml with kernel process tracing to see
what the syscalls return.
28407 ocamlrun CALL socketpair(0x1,0x1,0,0xbffff268)
28407 ocamlrun RET socketpair 0
28407 ocamlrun CALL getsockname(0x5,0xbffff204,0xbffff200)
28407 ocamlrun RET getsockname 0
28407 ocamlrun GIO fd 1 wrote 56 bytes
"Exception: Unix.Unix_error (Unix.EAFNOSUPPORT, "", "").
So both socketpair and getsockname return 0 but OCaml still complains.
My version of getsockname.c below outputs:
unix_getsockname: sock = 5, len = 0, retcode = 0
Exception: Unix.Unix_error (Unix.EAFNOSUPPORT, "", "").
Any suggestions?
Thanks, Joel
---
CAMLprim value unix_getsockname(value sock)
{
int retcode;
union sock_addr_union addr;
socklen_param_type addr_len;
addr_len = sizeof(addr);
retcode = getsockname(Int_val(sock), &addr.s_gen, &addr_len);
printf("unix_getsockname: sock = %d, len = %d, retcode = %d\n",
Int_val(sock), addr_len, retcode);
if (retcode == -1) uerror("getsockname", Nothing);
return alloc_sockaddr(&addr, addr_len, -1);
}
--
http://wagerlabs.com/
^ permalink raw reply [flat|nested] 13+ messages in thread