5 Copyright 2004 University of Cambridge
8 (***************************************************************************)
9 (* The watcher process starts a resolution process when it receives a *)
10 (* message from Isabelle *)
11 (* Signals Isabelle, puts output of child into pipe to Isabelle, *)
12 (* and removes dead processes. Also possible to kill all the resolution *)
13 (* processes currently running. *)
14 (* Hardwired version of where to pick up the tptp files for the moment *)
15 (***************************************************************************)
17 (*use "Proof_Transfer";
18 use "VampireCommunication";
19 use "SpassCommunication";*)
20 (*use "/homes/clq20/Jia_Code/TransStartIsar";*)
23 structure Watcher: WATCHER =
26 val goals_being_watched = ref 0;
28 (*****************************************)
29 (* The result of calling createWatcher *)
30 (*****************************************)
32 datatype proc = PROC of {
33 pid : Posix.Process.pid,
34 instr : TextIO.instream,
35 outstr : TextIO.outstream
38 (*****************************************)
39 (* The result of calling executeToList *)
40 (*****************************************)
42 datatype cmdproc = CMDPROC of {
43 prover: string, (* Name of the resolution prover used, e.g. Vampire, SPASS *)
44 cmd: string, (* The file containing the goal for res prover to prove *)
45 thmstring: string, (* string representation of subgoal after negation, skolemization*)
46 goalstring: string, (* string representation of subgoal*)
47 proc_handle : (TextIO.instream,TextIO.outstream) Unix.proc,
48 instr : TextIO.instream, (* Input stream to child process *)
49 outstr : TextIO.outstream (* Output stream from child process *)
52 type signal = Posix.Signal.signal
53 datatype exit_status = datatype Posix.Process.exit_status
55 val fromStatus = Posix.Process.fromStatus
58 fun reap(pid, instr, outstr) =
60 val u = TextIO.closeIn instr;
61 val u = TextIO.closeOut outstr;
64 Posix.Process.waitpid(Posix.Process.W_CHILD pid, [])
69 fun fdReader (name : string, fd : Posix.IO.file_desc) =
70 Posix.IO.mkTextReader {initBlkMode = true,name = name,fd = fd };
72 fun fdWriter (name, fd) =
73 Posix.IO.mkTextWriter {
81 fun openOutFD (name, fd) =
83 TextIO.StreamIO.mkOutstream (
84 fdWriter (name, fd), IO.BLOCK_BUF));
86 fun openInFD (name, fd) =
88 TextIO.StreamIO.mkInstream (
89 fdReader (name, fd), ""));
95 fun killChild child_handle = Unix.reap child_handle
97 fun childInfo (PROC{pid,instr,outstr }) = (pid,(instr,outstr));
99 fun cmdstreamsOf (CMDPROC{instr,outstr,...}) = (instr, outstr);
101 fun cmdInStream (CMDPROC{instr,outstr,...}) = (instr);
103 fun cmdchildInfo (CMDPROC{prover,cmd,thmstring,proc_handle,goalstring,instr,outstr}) = (prover,(cmd, (instr,outstr)));
105 fun cmdchildHandle (CMDPROC{prover,cmd,thmstring,goalstring,proc_handle,instr,outstr}) = proc_handle;
107 fun cmdProver (CMDPROC{prover,cmd,thmstring,goalstring,proc_handle,instr,outstr}) = (prover);
109 fun cmdThm (CMDPROC{prover,cmd,thmstring,goalstring,proc_handle,instr,outstr}) = (thmstring);
111 fun cmdGoal (CMDPROC{prover,cmd,thmstring,goalstring,proc_handle,instr,outstr}) = (goalstring);
113 fun sendOutput (outstr,str) = (TextIO.outputSubstr (outstr, (Substring.all str));TextIO.flushOut outstr);
115 (********************************************************************************************)
116 (* takes a list of arguments and sends them individually to the watcher process by pipe *)
117 (********************************************************************************************)
119 fun outputArgs (toWatcherStr, []) = ()
120 | outputArgs (toWatcherStr, (x::xs)) = (TextIO.output (toWatcherStr, x);
121 TextIO.flushOut toWatcherStr;
122 outputArgs (toWatcherStr, xs))
124 (********************************************************************************)
125 (* gets individual args from instream and concatenates them into a list *)
126 (********************************************************************************)
128 fun getArgs (fromParentStr, toParentStr,ys) = let
129 val thisLine = TextIO.input fromParentStr
134 (********************************************************************************)
135 (* Remove the \n character from the end of each filename *)
136 (********************************************************************************)
138 fun getCmd cmdStr = let val backList = ((rev(explode cmdStr)))
140 if (String.isPrefix "\n" (implode backList ))
141 then (implode (rev ((tl backList))))
145 (********************************************************************************)
146 (* Send request to Watcher for a vampire to be called for filename in arg *)
147 (********************************************************************************)
149 fun callResProver (toWatcherStr, arg) = (sendOutput (toWatcherStr, arg^"\n");
150 TextIO.flushOut toWatcherStr)
152 (*****************************************************************************************)
153 (* Send request to Watcher for multiple provers to be called for filenames in arg *)
154 (* need to do the dfg stuff in the watcher, not here! send over the clasimp and stuff files too*)
155 (*****************************************************************************************)
158 (* need to modify to send over hyps file too *)
159 fun callResProvers (toWatcherStr, []) =
160 (sendOutput (toWatcherStr, "End of calls\n"); TextIO.flushOut toWatcherStr)
161 | callResProvers (toWatcherStr,
162 (prover,thmstring,goalstring, proverCmd,settings,clasimpfile,
163 axfile, hypsfile,probfile) :: args) =
164 let val _ = File.write (File.tmp_path (Path.basic "tog_comms"))
165 (prover^thmstring^goalstring^proverCmd^settings^
166 clasimpfile^hypsfile^probfile)
167 in sendOutput (toWatcherStr,
168 (prover^"*"^thmstring^"*"^goalstring^"*"^proverCmd^"*"^
169 settings^"*"^clasimpfile^"*"^hypsfile^"*"^probfile^"\n"));
170 goals_being_watched := (!goals_being_watched) + 1;
171 TextIO.flushOut toWatcherStr;
172 callResProvers (toWatcherStr,args)
177 fun callResProversStr (toWatcherStr, []) = "End of calls\n"
179 | callResProversStr (toWatcherStr,(prover,thmstring,goalstring, proverCmd,settings,clasimpfile, axfile, hypsfile, probfile)::args) =
180 ((prover^"*"^thmstring^"*"^goalstring^"*"^proverCmd^"*"^settings^"*"^clasimpfile^"*"^axfile^"*"^hypsfile^"*"^probfile^"\n")
184 (**************************************************************)
185 (* Send message to watcher to kill currently running vampires *)
186 (**************************************************************)
188 fun callSlayer (toWatcherStr) = (sendOutput (toWatcherStr, "Kill vampires\n");
189 TextIO.flushOut toWatcherStr)
193 (**************************************************************)
194 (* Remove \n token from a vampire goal filename and extract *)
195 (* prover, proverCmd, settings and file from input string *)
196 (**************************************************************)
199 fun takeUntil ch [] res = (res, [])
200 | takeUntil ch (x::xs) res = if x = ch
204 takeUntil ch xs (res@[x])
206 fun getSettings [] settings = settings
207 | getSettings (xs) settings = let val (set, rest ) = takeUntil "%" xs []
209 getSettings rest (settings@[(implode set)])
212 fun separateFields str =
213 let val outfile = TextIO.openAppend(*("sep_field")*)(File.platform_path(File.tmp_path (Path.basic "sep_field")))
214 val _ = TextIO.output (outfile,("In separateFields, str is: "^(implode str)^"\n\n") )
215 val _ = TextIO.closeOut outfile
216 val (prover, rest) = takeUntil "*" str []
217 val prover = implode prover
219 val (thmstring, rest) = takeUntil "*" rest []
220 val thmstring = implode thmstring
222 val (goalstring, rest) = takeUntil "*" rest []
223 val goalstring = implode goalstring
225 val (proverCmd, rest ) = takeUntil "*" rest []
226 val proverCmd = implode proverCmd
228 val (settings, rest) = takeUntil "*" rest []
229 val settings = getSettings settings []
231 val (clasimpfile, rest ) = takeUntil "*" rest []
232 val clasimpfile = implode clasimpfile
234 val (hypsfile, rest ) = takeUntil "*" rest []
235 val hypsfile = implode hypsfile
237 val (file, rest) = takeUntil "*" rest []
238 val file = implode file
240 val _ = File.append (File.tmp_path (Path.basic "sep_comms"))
241 ("Sep comms are: "^(implode str)^"**"^
242 prover^thmstring^goalstring^proverCmd^clasimpfile^hypsfile^file^"\n\n")
244 (prover,thmstring,goalstring, proverCmd, settings, clasimpfile, hypsfile, file)
248 (***********************************************************************************)
249 (* do tptp2x and cat to turn clasimpfile, hypsfile and probfile into one .dfg file *)
250 (***********************************************************************************)
252 fun formatCmd (prover,thmstring,goalstring, proverCmd, settings, clasimpfile, hypsfile ,probfile) =
254 (*** want to cat clasimp ax hyps prob, then send the resulting file to tptp2x ***)
255 val probID = List.last(explode probfile)
256 val wholefile = File.tmp_path (Path.basic ("ax_prob_" ^ probID))
258 (*** only include problem and clasimp for the moment, not sure
259 how to refer to hyps/local axioms just now ***)
260 val whole_prob_file = Unix.execute("/bin/cat",
261 [clasimpfile,(*axfile, hypsfile,*)probfile, ">",
262 File.platform_path wholefile])
264 val dfg_dir = File.tmp_path (Path.basic "dfg");
265 (*** check if the directory exists and, if not, create it***)
267 if File.exists dfg_dir then warning("dfg dir exists")
268 else File.mkdir dfg_dir;
269 val dfg_path = File.platform_path dfg_dir;
271 val tptp2X = getenv "TPTP2X_HOME" ^ "/tptp2X"
273 val _ = if File.exists (File.unpack_platform_path tptp2X) then ()
274 else error ("Could not find the file " ^ tptp2X)
276 val bar = (fn s => (File.write (File.tmp_path (Path.basic "tptp2X-call")) s; system s))
277 (tptp2X ^ " -fdfg -d " ^ dfg_path ^ " " ^ File.platform_path wholefile)
278 val newfile = dfg_path ^ "/ax_prob" ^ "_" ^ probID ^ ".dfg"
279 val _ = File.append (File.tmp_path (Path.basic "thmstring_in_watcher"))
280 (thmstring ^ "\n goals_watched" ^
281 string_of_int(!goals_being_watched) ^ newfile ^ "\n")
284 (prover,thmstring,goalstring, proverCmd, settings,newfile)
288 (* remove \n from end of command and put back into tuple format *)
291 (* val cmdStr = "spass*((ALL xa. (~ P x | P xa) & (~ P xa | P x)) & (P xa | (ALL x. P x)) & ((ALL x. ~ P x) | ~ P xb) [.])*(EX x. ALL y. P x = P y) --> (EX x. P x) = (ALL y. P y)*/homes/clq20/bin/SPASS*-DocProof*/local/scratch/clq20/27023/clasimp*/local/scratch/clq20/27023/hyps*/local/scratch/clq20/27023/prob_1\n" *)
293 (*FIX: are the two getCmd procs getting confused? Why do I have two anyway? *)
296 let val backList = rev(explode cmdStr)
297 val _ = File.append (File.tmp_path (Path.basic"cmdStr")) cmdStr
299 if (String.isPrefix "\n" (implode backList ))
301 let val newCmdStr = (rev(tl backList))
302 in File.write (File.tmp_path (Path.basic"backlist"))
303 ("about to call sepfields with "^(implode newCmdStr));
304 formatCmd (separateFields newCmdStr)
306 else formatCmd (separateFields (explode cmdStr))
310 fun getProofCmd (a,b,c,d,e,f) = d
313 (**************************************************************)
314 (* Get commands from Isabelle *)
315 (**************************************************************)
316 (* FIX: or perhaps do the tptp2x stuff here - so it's get commands and then format them, before passing them to spass *)
318 fun getCmds (toParentStr,fromParentStr, cmdList) =
319 let val thisLine = TextIO.inputLine fromParentStr
320 val _ = File.append (File.tmp_path (Path.basic "parent_comms")) thisLine
322 if (thisLine = "End of calls\n")
324 else if (thisLine = "Kill children\n")
326 ( TextIO.output (toParentStr,thisLine );
327 TextIO.flushOut toParentStr;
328 (("","","","Kill children",[],"")::cmdList)
330 else let val thisCmd = getCmd (thisLine)
331 (*********************************************************)
332 (* thisCmd = (prover,thmstring,proverCmd, settings, file)*)
333 (* i.e. put back into tuple format *)
334 (*********************************************************)
336 (*TextIO.output (toParentStr, thisCmd);
337 TextIO.flushOut toParentStr;*)
338 getCmds (toParentStr,fromParentStr, (thisCmd::cmdList))
343 (**************************************************************)
344 (* Get Io-descriptor for polling of an input stream *)
345 (**************************************************************)
348 fun getInIoDesc someInstr =
349 let val (rd, buf) = TextIO.StreamIO.getReader(TextIO.getInstream someInstr)
350 val _ = TextIO.output (TextIO.stdOut, buf)
353 of TextPrimIO.RD{ioDesc = SOME iod, ...} =>SOME iod
355 in (* since getting the reader will have terminated the stream, we need
356 * to build a new stream. *)
357 TextIO.setInstream(someInstr, TextIO.StreamIO.mkInstream(rd, buf));
362 (*************************************)
363 (* Set up a Watcher Process *)
364 (*************************************)
368 fun setupWatcher (thm,clause_arr, num_of_clauses) =
370 (** pipes for communication between parent and watcher **)
371 val p1 = Posix.IO.pipe ()
372 val p2 = Posix.IO.pipe ()
374 Posix.IO.close (#outfd p1);
375 Posix.IO.close (#infd p1);
376 Posix.IO.close (#outfd p2);
377 Posix.IO.close (#infd p2)
379 (***********************************************************)
380 (****** fork a watcher process and get it set up and going *)
381 (***********************************************************)
382 fun startWatcher (procList) =
383 (case Posix.Process.fork() (***************************************)
384 of SOME pid => pid (* parent - i.e. main Isabelle process *)
385 (***************************************)
387 (*************************)
388 | NONE => let (* child - i.e. watcher *)
389 val oldchildin = #infd p1 (*************************)
390 val fromParent = Posix.FileSys.wordToFD 0w0
391 val oldchildout = #outfd p2
392 val toParent = Posix.FileSys.wordToFD 0w1
393 val fromParentIOD = Posix.FileSys.fdToIOD fromParent
394 val fromParentStr = openInFD ("_exec_in_parent", fromParent)
395 val toParentStr = openOutFD ("_exec_out_parent", toParent)
396 val sign = sign_of_thm thm
397 val prems = prems_of thm
398 val prems_string = Meson.concat_with_and (map (Sign.string_of_term sign) prems)
399 val _ = (warning ("subgoals forked to startWatcher: "^prems_string));
401 (*val tenth_ax = fst( Array.sub(clause_arr, 1))
402 val tenth_ax_thms = memo_find_clause (tenth_ax, clause_tab)
403 val clause_str = Meson.concat_with_and (map string_of_thm tenth_ax_thms)
404 val _ = (warning ("tenth axiom in array in watcher is: "^tenth_ax))
405 val _ = (warning ("tenth axiom in table in watcher is: "^clause_str))
406 val _ = (warning ("num_of_clauses in watcher is: "^(string_of_int (num_of_clauses))) )
408 (*val goalstr = string_of_thm (the_goal)
409 val outfile = TextIO.openOut(File.platform_path(File.tmp_path (Path.basic "goal_in_watcher")));
410 val _ = TextIO.output (outfile,goalstr )
411 val _ = TextIO.closeOut outfile*)
412 fun killChildren [] = ()
413 | killChildren (child_handle::children) = (killChild child_handle; killChildren children)
417 (*************************************************************)
418 (* take an instream and poll its underlying reader for input *)
419 (*************************************************************)
421 fun pollParentInput () =
422 let val pd = OS.IO.pollDesc (fromParentIOD)
425 let val pd' = OS.IO.pollIn (valOf pd)
426 val pdl = OS.IO.poll ([pd'], SOME (Time.fromMilliseconds 2000))
427 val _ = File.append (File.tmp_path (Path.basic "parent_poll"))
433 else if (OS.IO.isIn (hd pdl))
435 (SOME ( getCmds (toParentStr, fromParentStr, [])))
443 fun pollChildInput (fromStr) =
444 let val iod = getInIoDesc fromStr
448 let val pd = OS.IO.pollDesc (valOf iod)
451 let val pd' = OS.IO.pollIn (valOf pd)
452 val pdl = OS.IO.poll ([pd'], SOME (Time.fromMilliseconds 2000))
453 val _ = File.append (File.tmp_path (Path.basic "child_poll"))
459 else if (OS.IO.isIn (hd pdl))
461 SOME ((*getCmd*) (TextIO.inputLine fromStr))
473 (****************************************************************************)
474 (* Check all vampire processes currently running for output *)
475 (****************************************************************************)
476 (*********************************)
477 fun checkChildren ([], toParentStr) = [] (*** no children to check ********)
478 (*********************************)
479 | checkChildren ((childProc::otherChildren), toParentStr) =
480 let val _ = File.append (File.tmp_path (Path.basic "child_check"))
481 ("In check child, length of queue:"^(string_of_int (length (childProc::otherChildren)))^"\n")
482 val (childInput,childOutput) = cmdstreamsOf childProc
483 val child_handle= cmdchildHandle childProc
484 (* childCmd is the .dfg file that the problem is in *)
485 val childCmd = fst(snd (cmdchildInfo childProc))
486 val _ = File.append (File.tmp_path (Path.basic "child_command"))
488 (* now get the number of the subgoal from the filename *)
489 val sg_num = int_of_string(ReconOrderClauses.get_nth 5 (rev(explode childCmd)))
490 val childIncoming = pollChildInput childInput
491 val _ = File.append (File.tmp_path (Path.basic "child_check_polled"))
492 ("finished polling child \n")
493 val parentID = Posix.ProcEnv.getppid()
494 val prover = cmdProver childProc
495 val thmstring = cmdThm childProc
496 val sign = sign_of_thm thm
497 val prems = prems_of thm
498 val prems_string = Meson.concat_with_and (map (Sign.string_of_term sign) prems)
499 val _ = warning("subgoals forked to checkChildren: "^prems_string)
500 val goalstring = cmdGoal childProc
501 val _ = File.append (File.tmp_path (Path.basic "child_comms"))
502 (prover^thmstring^goalstring^childCmd^"\n")
504 if (isSome childIncoming)
506 (* check here for prover label on child*)
507 let val _ = File.write (File.tmp_path (Path.basic "child_incoming")) ("subgoals forked to checkChildren: "^prems_string^prover^thmstring^goalstring^childCmd)
508 val childDone = (case prover of
509 (* "vampire" => startVampireTransfer(childInput, toParentStr, parentID, childCmd) |*)"spass" => (SpassComm.checkSpassProofFound(childInput, toParentStr, parentID,thmstring,goalstring, childCmd, thm, sg_num,clause_arr, num_of_clauses) ) )
511 if childDone (**********************************************)
512 then (* child has found a proof and transferred it *)
513 (**********************************************)
515 (**********************************************)
516 (* Remove this child and go on to check others*)
517 (**********************************************)
518 ( Unix.reap child_handle;
519 checkChildren(otherChildren, toParentStr))
521 (**********************************************)
522 (* Keep this child and go on to check others *)
523 (**********************************************)
525 (childProc::(checkChildren (otherChildren, toParentStr)))
528 (File.append (File.tmp_path (Path.basic "child_incoming")) "No child output ";
529 childProc::(checkChildren (otherChildren, toParentStr)))
533 (********************************************************************)
534 (* call resolution processes *)
535 (* settings should be a list of strings *)
536 (* e.g. ["-t 300", "-m 100000"] *)
537 (* takes list of (string, string, string list, string)list proclist *)
538 (********************************************************************)
541 (*** add subgoal id num to this *)
542 fun execCmds [] procList = procList
543 | execCmds ((prover, thmstring,goalstring,proverCmd,settings,file)::cmds) procList = let val _ = File.append (File.tmp_path (Path.basic "pre_exec_child")) ("About to execute command for goal:\n"^goalstring^proverCmd^(concat settings)^file^" at "^(Date.toString(Date.fromTimeLocal(Time.now()))))
545 if (prover = "spass")
547 let val childhandle:(TextIO.instream,TextIO.outstream) Unix.proc = (Unix.execute(proverCmd, (["-FullRed=0"]@settings@[file])))
548 val (instr, outstr)=Unix.streamsOf childhandle
549 val newProcList = (((CMDPROC{
552 thmstring = thmstring,
553 goalstring = goalstring,
554 proc_handle = childhandle,
556 outstr = outstr })::procList))
557 val _ = File.append (File.tmp_path (Path.basic "exec_child")) ("executing command for goal:\n"^goalstring^proverCmd^(concat settings)^file^" at "^(Date.toString(Date.fromTimeLocal(Time.now()))))
559 Posix.Process.sleep (Time.fromSeconds 1);execCmds cmds newProcList
562 let val childhandle:(TextIO.instream,TextIO.outstream) Unix.proc = (Unix.execute(proverCmd, (settings@[file])))
563 val (instr, outstr)=Unix.streamsOf childhandle
564 val newProcList = (((CMDPROC{
567 thmstring = thmstring,
568 goalstring = goalstring,
569 proc_handle = childhandle,
571 outstr = outstr })::procList))
573 Posix.Process.sleep (Time.fromSeconds 1); execCmds cmds newProcList
578 (****************************************)
579 (* call resolution processes remotely *)
580 (* settings should be a list of strings *)
581 (* e.g. ["-t 300", "-m 100000"] *)
582 (****************************************)
584 (* fun execRemoteCmds [] procList = procList
585 | execRemoteCmds ((prover, thmstring,goalstring,proverCmd ,settings,file)::cmds) procList =
586 let val newProcList = mySshExecuteToList ("/usr/bin/ssh",([prover,thmstring,goalstring,"-t", "shep"]@[proverCmd]@settings@[file]), procList)
588 execRemoteCmds cmds newProcList
592 fun printList (outStr, []) = ()
593 | printList (outStr, (x::xs)) = (TextIO.output (outStr, x);TextIO.flushOut outStr; printList (outStr,xs))
596 (**********************************************)
598 (**********************************************)
603 fun keepWatching (toParentStr, fromParentStr,procList) =
604 let fun loop (procList) =
606 let val cmdsFromIsa = pollParentInput ()
607 fun killchildHandler (n:int) = (TextIO.output(toParentStr, "Killing child proof processes!\n");
608 TextIO.flushOut toParentStr;
609 killChildren (map (cmdchildHandle) procList);
613 (*Signal.signal (Posix.Signal.usr2, Signal.SIG_HANDLE killchildHandler);*)
614 (**********************************)
615 if (isSome cmdsFromIsa) then (* deal with input from Isabelle *)
616 ( (**********************************)
617 if (getProofCmd(hd(valOf cmdsFromIsa)) = "Kill children" )
620 let val child_handles = map cmdchildHandle procList
622 killChildren child_handles;
623 (*Posix.Process.kill(Posix.Process.K_PROC (Posix.ProcEnv.getppid()), Posix.Signal.usr2);*) loop ([])
629 if ((length procList)<10) (********************)
630 then (* Execute locally *)
631 ( (********************)
633 val newProcList = execCmds (valOf cmdsFromIsa) procList
634 val parentID = Posix.ProcEnv.getppid()
635 val _ = (File.append (File.tmp_path (Path.basic "prekeep_watch")) "Just execed a child\n ")
636 val newProcList' =checkChildren (newProcList, toParentStr)
638 val _ = warning("off to keep watching...")
639 val _ = (File.append (File.tmp_path (Path.basic "keep_watch")) "Off to keep watching...\n ")
641 (*Posix.Process.sleep (Time.fromSeconds 1);*)
645 else (*********************************)
646 (* Execute remotely *)
647 (* (actually not remote for now )*)
648 ( (*********************************)
650 val newProcList = execCmds (valOf cmdsFromIsa) procList
651 val parentID = Posix.ProcEnv.getppid()
652 val newProcList' =checkChildren (newProcList, toParentStr)
654 (*Posix.Process.sleep (Time.fromSeconds 1);*)
662 ) (******************************)
663 else (* No new input from Isabelle *)
664 (******************************)
665 ( let val newProcList = checkChildren ((procList), toParentStr)
667 (*Posix.Process.sleep (Time.fromSeconds 1);*)
668 (File.append (File.tmp_path (Path.basic "keep_watch")) "Off to keep watching.2..\n ");
680 (***************************)
681 (*** Sort out pipes ********)
682 (***************************)
684 Posix.IO.close (#outfd p1);
685 Posix.IO.close (#infd p2);
686 Posix.IO.dup2{old = oldchildin, new = fromParent};
687 Posix.IO.close oldchildin;
688 Posix.IO.dup2{old = oldchildout, new = toParent};
689 Posix.IO.close oldchildout;
691 (***************************)
692 (* start the watcher loop *)
693 (***************************)
694 keepWatching (toParentStr, fromParentStr, procList);
697 (****************************************************************************)
698 (* fake return value - actually want the watcher to loop until killed *)
699 (****************************************************************************)
700 Posix.Process.wordToPid 0w0
706 val _ = TextIO.flushOut TextIO.stdOut
708 (*******************************)
709 (*** set watcher going ********)
710 (*******************************)
713 val pid = startWatcher (procList)
714 (**************************************************)
715 (* communication streams to watcher *)
716 (**************************************************)
718 val instr = openInFD ("_exec_in", #infd p2)
719 val outstr = openOutFD ("_exec_out", #outfd p1)
722 (*******************************)
723 (* close the child-side fds *)
724 (*******************************)
725 Posix.IO.close (#outfd p2);
726 Posix.IO.close (#infd p1);
727 (* set the fds close on exec *)
728 Posix.IO.setfd (#infd p2, Posix.IO.FD.flags [Posix.IO.FD.cloexec]);
729 Posix.IO.setfd (#outfd p1, Posix.IO.FD.flags [Posix.IO.FD.cloexec]);
731 (*******************************)
733 (*******************************)
742 (**********************************************************)
743 (* Start a watcher and set up signal handlers *)
744 (**********************************************************)
746 fun killWatcher pid= Posix.Process.kill(Posix.Process.K_PROC pid, Posix.Signal.kill);
748 fun reapWatcher(pid, instr, outstr) =
750 val u = TextIO.closeIn instr;
751 val u = TextIO.closeOut outstr;
754 Posix.Process.waitpid(Posix.Process.W_CHILD pid, [])
760 fun createWatcher (thm,clause_arr, ( num_of_clauses:int)) = let val mychild = childInfo (setupWatcher(thm,clause_arr, num_of_clauses))
761 val streams =snd mychild
762 val childin = fst streams
763 val childout = snd streams
764 val childpid = fst mychild
765 val sign = sign_of_thm thm
766 val prems = prems_of thm
767 val prems_string = Meson.concat_with_and (map (Sign.string_of_term sign) prems)
768 val _ = (warning ("subgoals forked to createWatcher: "^prems_string));
769 fun vampire_proofHandler (n) =
770 (Pretty.writeln(Pretty.str ( (concat[(oct_char "360"), (oct_char "377")])));
771 getVampInput childin; Pretty.writeln(Pretty.str (oct_char "361"));() )
774 fun spass_proofHandler (n) = (
775 let val outfile = TextIO.openOut(File.platform_path(File.tmp_path (Path.basic "foo_signal1")));
776 val _ = TextIO.output (outfile, ("In signal handler now\n"))
777 val _ = TextIO.closeOut outfile
778 val (reconstr, thmstring, goalstring) = SpassComm.getSpassInput childin
779 val outfile = TextIO.openAppend(File.platform_path(File.tmp_path (Path.basic "foo_signal")));
781 val _ = TextIO.output (outfile, ("In signal handler "^reconstr^thmstring^goalstring^"goals_being_watched is: "^(string_of_int (!goals_being_watched))))
782 val _ = TextIO.closeOut outfile
783 in (* if a proof has been found and sent back as a reconstruction proof *)
784 if ( (substring (reconstr, 0,1))= "[")
788 Pretty.writeln(Pretty.str ( (concat[(oct_char "360"), (oct_char "377")])));
789 Recon_Transfer.apply_res_thm reconstr goalstring;
790 Pretty.writeln(Pretty.str (oct_char "361"));
792 goals_being_watched := ((!goals_being_watched) - 1);
794 if ((!goals_being_watched) = 0)
796 (let val outfile = TextIO.openOut(File.platform_path(File.tmp_path (Path.basic "foo_reap_found")));
797 val _ = TextIO.output (outfile, ("Reaping a watcher, goals watched is: "^(string_of_int (!goals_being_watched))^"\n"))
798 val _ = TextIO.closeOut outfile
800 killWatcher (childpid); reapWatcher (childpid,childin, childout); ()
805 (* if there's no proof, but a message from Spass *)
806 else if ((substring (reconstr, 0,5))= "SPASS")
809 goals_being_watched := (!goals_being_watched) -1;
810 Pretty.writeln(Pretty.str ( (concat[(oct_char "360"), (oct_char "377")])));
811 Pretty.writeln(Pretty.str (goalstring^reconstr));
812 Pretty.writeln(Pretty.str (oct_char "361"));
813 if (!goals_being_watched = 0)
815 (let val outfile = TextIO.openOut(File.platform_path(File.tmp_path (Path.basic "foo_reap_comp")));
816 val _ = TextIO.output (outfile, ("Reaping a watcher, goals watched is: "^(string_of_int (!goals_being_watched))^"\n"))
817 val _ = TextIO.closeOut outfile
819 killWatcher (childpid); reapWatcher (childpid,childin, childout); ()
824 (* print out a list of rules used from clasimpset*)
825 else if ((substring (reconstr, 0,5))= "Rules")
828 goals_being_watched := (!goals_being_watched) -1;
829 Pretty.writeln(Pretty.str ( (concat[(oct_char "360"), (oct_char "377")])));
830 Pretty.writeln(Pretty.str (goalstring^reconstr));
831 Pretty.writeln(Pretty.str (oct_char "361"));
832 if (!goals_being_watched = 0)
834 (let val outfile = TextIO.openOut(File.platform_path(File.tmp_path (Path.basic "foo_reap_comp")));
835 val _ = TextIO.output (outfile, ("Reaping a watcher, goals watched is: "^(string_of_int (!goals_being_watched))^"\n"))
836 val _ = TextIO.closeOut outfile
838 killWatcher (childpid); reapWatcher (childpid,childin, childout);()
844 (* if proof translation failed *)
845 else if ((substring (reconstr, 0,5)) = "Proof")
848 goals_being_watched := (!goals_being_watched) -1;
849 Pretty.writeln(Pretty.str ( (concat[(oct_char "360"), (oct_char "377")])));
850 Pretty.writeln(Pretty.str (goalstring^(Recon_Transfer.restore_linebreaks reconstr)));
851 Pretty.writeln(Pretty.str (oct_char "361"));
852 if (!goals_being_watched = 0)
854 (let val outfile = TextIO.openOut(File.platform_path (File.tmp_path (Path.basic "foo_reap_comp")));
855 val _ = TextIO.output (outfile, ("Reaping a watcher, goals watched is: "^(string_of_int (!goals_being_watched))^"\n"))
856 val _ = TextIO.closeOut outfile
858 killWatcher (childpid); reapWatcher (childpid,childin, childout); ()
865 else (* add something here ?*)
872 in IsaSignal.signal (IsaSignal.usr1, IsaSignal.SIG_HANDLE vampire_proofHandler);
873 IsaSignal.signal (IsaSignal.usr2, IsaSignal.SIG_HANDLE spass_proofHandler);
874 (childin, childout, childpid)
883 end (* structure Watcher *)