Xander
Xander

Reputation: 11

How do I stop the execution of a command-line argument in Scala if the program runs for too long?

I am attempting to run a program from the commandline that will run indefinitely if the image file passed through the program is corrupted and/or the named is wrong. I can test to make sure the filename is valid, but that won't help me if a rootkit damaged the image. My understanding is that the only way to quit the program is to create a separate thread, but sys.process.!! blocks until execution is completed.

val imageInfo: Option[String] = Some(s"python vol.py -f $memFile imageinfo".!!.trim)

Upvotes: 1

Views: 930

Answers (2)

chengpohi
chengpohi

Reputation: 14217

You can use Future with Await to measure the too long Process, like:

  import scala.concurrent.ExecutionContext.Implicits.global

  val sb = new StringBuffer // sb for capture output
  val io = BasicIO(false, sb, None)// Creates a `ProcessIO` that appends its output to a `StringBuffer`
  val p = s"python vol.py -f $memFile imageinfo".run()

  val f = Future {
    p.exitValue() //Blocks until this process exits and returns the exit code.
    Some(sb.toString)// return the process result
  }

  try {
    val str: Option[String] = Await.result(f, Duration.apply(1, TimeUnit.SECONDS))
  } catch {
    case e: TimeoutException => {
      println("run too long")
      p.destroy() //destroy this process when too long
    }
  }

Upvotes: 0

jwvh
jwvh

Reputation: 51271

You don't have to let a Process block until its completion.

import scala.sys.process.{Process, ProcessLogger}

var (iiOut, iiErr) = ("", "")  // for collecting Process output
val getii = Process(s"python vol.py -f $memFile imageinfo")
                 .run(ProcessLogger(iiOut += _, iiErr += _))

// . . .
// do other useful stuff
// or set a timeout alarm and wait for it
// . . .

val imageInfo: Option[String] =
  if (getii.isAlive()) {
    // report failure
    getii.destroy()
    None
  } else if (getii.exitValue() != 0 || iiErr != "") {
    // report failure
    None
  } else
    Some(iiOut.trim)

Upvotes: 1

Related Questions