[MLton] bug in MLton and bug in basis

Stephen Weeks MLton@mlton.org
Fri, 19 Aug 2005 08:38:53 -0700


> > -      val getERROR = getSockOptBool (Prim.Ctl.SOCKET, Prim.Ctl.ERROR)
> > +      fun getERROR s =
> > +         getSockOptInt (Prim.Ctl.SOCKET, Prim.Ctl.ERROR) s
> > +         handle Error.SysErr (_, e) =>
> > +            case e of
> > +               NONE => raise Fail "Socket.Ctl.getERROR"
> > +             | SOME s => s
> 
> ... won't work. SysErr ("Connection Refused", NONE) for example.
> 
> You should do like I said earlier: return SysErr option...
> 
> fun getERROR s =
>      case getSockOptInt (Prim.Ctl.SOCKET, Prim.Ctl.ERROR) s of
>          0 => NONE
>      |   x => SOME (MakeASysErrUsingStrerror x)
>       handle ex => SOME ex

I'm a bit confused what you mean by "SysErr" as a type.  I think that
returning "exn option", as your code suggests, is not as precise as it
could be.  However, your point that one might see Error.SysErr (...,
NONE) argues that returning "Posix.Error.syserror option" is not right
either.  I guess that returning an option of the argument type of the
SysErr exception is the right thing.  That is,

  (string * Posix.Error.syserror option) option

Here's a patch that does this.


Index: basis-library/mlton/socket.sig
===================================================================
--- basis-library/mlton/socket.sig	(revision 3997)
+++ basis-library/mlton/socket.sig	(working copy)
@@ -18,7 +18,9 @@
 
       structure Ctl:
          sig
-            val getERROR: ('af, 'sock_type) Socket.sock -> int
+            val getERROR:
+               ('af, 'sock_type) Socket.sock
+               -> (string * Posix.Error.syserror option) option
          end
 
       structure Host:
Index: basis-library/net/socket.sml
===================================================================
--- basis-library/net/socket.sml	(revision 3997)
+++ basis-library/net/socket.sml	(working copy)
@@ -212,11 +212,13 @@
       fun getTYPE s =
 	 Prim.SOCK.fromInt (getSockOptInt (Prim.Ctl.SOCKET, Prim.Ctl.TYPE) s)
       fun getERROR s =
-         getSockOptInt (Prim.Ctl.SOCKET, Prim.Ctl.ERROR) s
-         handle Error.SysErr (_, e) =>
-            case e of
-               NONE => raise Fail "Socket.Ctl.getERROR"
-             | SOME s => s
+         let
+            val se = getSockOptInt (Prim.Ctl.SOCKET, Prim.Ctl.ERROR) s
+         in
+            if 0 = se
+               then NONE
+            else SOME (Posix.Error.errorMsg se, SOME se)
+         end handle Error.SysErr z => SOME z
       local
 	 fun getName (s, f: Prim.sock * pre_sock_addr * int ref -> int) =
 	    let
@@ -237,7 +239,7 @@
    struct
       open CtlExtra
 
-      fun getERROR s = 0 < CtlExtra.getERROR s
+      val getERROR = isSome o CtlExtra.getERROR
    end
 
 fun sameAddr (SA sa1, SA sa2) = sa1 = sa2
Index: basis-library/net/socket.sig
===================================================================
--- basis-library/net/socket.sig	(revision 3997)
+++ basis-library/net/socket.sig	(working copy)
@@ -183,7 +183,9 @@
 (* 	  val setSockOptWord:
  * 	     level * optname -> ('af, 'sock_type) sock * word -> unit
  *)
-          val getERROR: ('af, 'sock_type) sock -> int
+          val getERROR:
+             ('af, 'sock_type) sock
+             -> (string * Posix.Error.syserror option) option
 	  val getSockOptInt: level * optname -> ('af, 'sock_type) sock -> int
 	  val setSockOptInt:
 	     level * optname -> ('af, 'sock_type) sock * int -> unit