@@ -8,8 +8,11 @@ import java.io.{
8
8
InputStream , ObjectInputStream ,
9
9
OutputStream , ObjectOutputStream
10
10
}
11
+ import java .util .concurrent .TimeoutException
11
12
12
13
import scala .concurrent .duration .Duration
14
+ import scala .concurrent .{ Await , Future }
15
+ import scala .concurrent .ExecutionContext .Implicits .global
13
16
import scala .collection .mutable
14
17
15
18
trait RunnerOrchestration {
@@ -35,8 +38,47 @@ trait RunnerOrchestration {
35
38
def runMain (dir : JFile ): Status = withRunner(_.runMain(dir))
36
39
37
40
private class Runner (private var process : Process ) {
38
- def kill (): Unit = ???
39
- def runMain (dir : JFile ): Status = ???
41
+ private [this ] val ois = new ObjectInputStream (process.getInputStream)
42
+ private [this ] val oos = new ObjectOutputStream (process.getOutputStream)
43
+
44
+ def kill (): Unit = {
45
+ if (process ne null ) process.destroy()
46
+ process = null
47
+ }
48
+
49
+ def runMain (dir : JFile ): Status = {
50
+ assert(process ne null ,
51
+ " Runner was killed and then reused without setting a new process" )
52
+
53
+ // Makes the encapsulating RunnerMonitor spawn a new runner
54
+ def respawn (): Unit = {
55
+ process.destroy()
56
+ process = createProcess
57
+ }
58
+
59
+ // pass file to running process
60
+ oos.writeObject(dir)
61
+
62
+ // Create a future reading the object:
63
+ val readObject = Future (ois.readObject().asInstanceOf [Status ])
64
+
65
+ // Await result for `maxDuration` and then timout and destroy the
66
+ // process:
67
+ val status =
68
+ try Await .result(readObject, maxDuration)
69
+ catch { case _ : TimeoutException => { Timeout } }
70
+
71
+ // Handle failure of the VM:
72
+ status match {
73
+ case _ if safeMode => respawn()
74
+ case status : Failure => respawn()
75
+ case Timeout => respawn()
76
+ case _ => ()
77
+ }
78
+
79
+ // return run status:
80
+ status
81
+ }
40
82
}
41
83
42
84
private def createProcess : Process = ???
0 commit comments