1 (* Copyright (C
) 2009 Matthew Fluet
.
2 * Copyright (C
) 1999-2006, 2008 Henry Cejtin
, Matthew Fluet
, Suresh
3 * Jagannathan
, and Stephen Weeks
.
4 * Copyright (C
) 1997-2000 NEC Research Institute
.
6 * MLton is released under a BSD
-style license
.
7 * See the file MLton
-LICENSE for details
.
10 structure PosixProcess
: POSIX_PROCESS_EXTRA
=
12 structure Prim
= PrimitiveFFI
.Posix
.Process
14 structure FileDesc
= PrePosix
.FileDesc
15 structure PId
= PrePosix
.PId
16 structure Signal
= PrePosix
.Signal
18 structure Error
= PosixError
19 structure SysCall
= Error
.SysCall
21 type signal
= Signal
.t
24 val pidToWord
= C_PId
.castToSysWord
o PId
.toRep
25 val wordToPid
= PId
.fromRep
o C_PId
.castFromSysWord
29 ({errVal
= C_PId
.castFromFixedInt ~
1}, fn () =>
30 (Prim
.fork (), fn p
=>
31 if p
= C_PId
.castFromFixedInt
0
33 else SOME (PId
.fromRep p
)))
36 if Primitive
.MLton
.Platform
.OS
.forkIsEnabled
38 else fn () => Error
.raiseSys Error
.nosys
40 val conv
= NullString
.nullTerm
41 val convs
= CUtil
.C_StringArray
.fromList
43 fun exece (path
, args
, env
): 'a
=
50 (fn () => Prim
.exece (path
, args
, env
))
51 ; raise Fail
"Posix.Process.exece")
54 fun exec (path
, args
): 'a
=
55 exece (path
, args
, PosixProcEnv
.environ ())
57 fun execp (file
, args
): 'a
=
63 (fn () => Prim
.execp (file
, args
))
64 ; raise Fail
"Posix.Process.execp")
67 datatype waitpid_arg
=
73 datatype exit_status
=
75 | W_EXITSTATUS
of Word8.word
76 | W_SIGNALED
of signal
79 fun fromStatus
' (status
: C_Status
.t
) =
80 if Prim
.ifExited status
<> C_Int
.zero
81 then (case Prim
.exitStatus status
of
83 | n
=> W_EXITSTATUS (Word8.castFromSysWord (C_Int
.castToSysWord n
)))
84 else if Prim
.ifSignaled status
<> C_Int
.zero
85 then W_SIGNALED (PosixSignal
.fromRep (Prim
.termSig status
))
86 else if Prim
.ifStopped status
<> C_Int
.zero
87 then W_STOPPED (PosixSignal
.fromRep (Prim
.stopSig status
))
88 else raise Fail
"Posix.Process.fromStatus"
89 fun fromStatus status
=
90 fromStatus
' (PreOS
.Status
.toRep status
)
94 structure Flags
= BitFlags(structure S
= C_Int
)
96 (* val continued
= CONTINUED
*)
98 val untraced
= UNTRACED
102 val status
: C_Status
.t ref
= ref (C_Status
.fromInt
0)
103 fun wait (wa
, status
, flags
) =
107 W_ANY_CHILD
=> C_PId
.castFromFixedInt ~
1
108 | W_CHILD pid
=> PId
.toRep pid
109 | W_SAME_GROUP
=> C_PId
.castFromFixedInt
0
110 | W_GROUP pid
=> C_PId
.~
(PId
.toRep pid
)
111 val flags
= W
.flags flags
113 (PId
.fromRep
o SysCall
.simpleResultRestart
')
114 ({errVal
= C_PId
.castFromFixedInt ~
1}, fn () =>
116 val pid
= Prim
.waitpid (pid
, status
, flags
)
121 fun getStatus () = fromStatus
' (!status
)
123 fun waitpid (wa
, flags
) =
125 val pid
= wait (wa
, status
, flags
)
130 fun waitpid_nh (wa
, flags
) =
132 val pid
= wait (wa
, status
, W
.nohang
:: flags
)
134 if PId
.fromRep (C_PId
.castFromFixedInt
0) = pid
136 else SOME (pid
, getStatus ())
140 fun wait () = waitpid (W_ANY_CHILD
, [])
142 fun exit (w
: Word8.word): 'a
=
143 (* Posix
.Process
.exit does not call atExit cleaners
, as per the basis
146 (Prim
.exit (C_Status
.castFromSysWord (Word8.castToSysWord w
))
147 ; raise Fail
"Posix.Process.exit")
149 datatype killpid_arg
=
154 fun kill (ka
: killpid_arg
, s
: signal
): unit
=
158 K_PROC pid
=> PId
.toRep pid
159 | K_SAME_GROUP
=> C_PId
.castFromFixedInt ~
1
160 | K_GROUP pid
=> C_PId
.~
(PId
.toRep pid
)
161 val s
= PosixSignal
.toRep s
163 SysCall
.simple (fn () => Prim
.kill (pid
, s
))
167 fun wrap
prim (t
: Time
.time
): Time
.time
=
171 ((C_UInt
.fromLargeInt (Time
.toSeconds t
))
172 handle Overflow
=> Error
.raiseSys Error
.inval
)))
174 val alarm
= wrap Prim
.alarm
175 (* val sleep
= wrap Prim
.sleep
*)
178 fun sleep (t
: Time
.time
): Time
.time
=
180 val t
= Time
.toNanoseconds t
181 val sec
= LargeInt
.quot (t
, 1000000000)
182 val nsec
= LargeInt
.rem (t
, 1000000000)
184 (C_Time
.fromLargeInt sec
, C_Long
.fromLargeInt nsec
)
185 handle Overflow
=> Error
.raiseSys Error
.inval
187 val nsecRem
= ref nsec
189 Time
.+ (Time
.fromSeconds (C_Time
.toLargeInt (!secRem
)),
190 Time
.fromNanoseconds (C_Long
.toLargeInt (!nsecRem
)))
193 ({clear
= false, restart
= false, errVal
= C_Int
.fromInt ~
1}, fn () =>
194 {handlers
= [(Error
.intr
, remaining
)],
196 return
= Prim
.nanosleep (secRem
, nsecRem
)})
202 ({clear
= false, restart
= false, errVal
= C_Int
.fromInt ~
1},
204 {return
= Prim
.pause (),
206 handlers
= [(Error
.intr
, fn () => ())]})