func (s *Contester) LocalExecuteConnected(request *contester_proto.LocalExecuteConnected, response *contester_proto.LocalExecuteConnectedResult) error { firstSandbox, err := findSandbox(s.Sandboxes, request.First) if err != nil { return err } secondSandbox, err := findSandbox(s.Sandboxes, request.Second) if err != nil { return err } firstSandbox.Mutex.Lock() defer firstSandbox.Mutex.Unlock() secondSandbox.Mutex.Lock() defer secondSandbox.Mutex.Unlock() err = chmodRequestIfNeeded(firstSandbox, request.First) if err != nil { return err } err = chmodRequestIfNeeded(secondSandbox, request.Second) if err != nil { return err } first, err := s.setupSubprocess(request.First, firstSandbox, false) if err != nil { return err } second, err := s.setupSubprocess(request.Second, secondSandbox, false) if err != nil { return err } err = subprocess.Interconnect(first, second, nil, nil) if err != nil { return err } cs := make(chan runResult, 1) outstanding := 2 go execAndSend(first, cs, false) go execAndSend(second, cs, true) for outstanding > 0 { r := <-cs outstanding-- if r.second { if r.e != nil { err = r.e } else { response.Second = &contester_proto.LocalExecutionResult{} fillResult(r.r, response.Second) } } else { if r.e != nil { err = r.e } else { response.First = &contester_proto.LocalExecutionResult{} fillResult(r.r, response.First) } } } return err }
func main() { programFlags, globalFlags, err := ParseFlags(true, os.Args[1:]) if err != nil { Fail(globalFlags.Xml, err, "Parse main flags") } if globalFlags.Logfile != "" { logfile, err := os.Create(globalFlags.Logfile) if err != nil { log.Fatal(err) } log.SetOutput(logfile) } var interactorFlags *ProcessConfig if globalFlags.Interactor != "" { interactorFlags, _, err = ParseFlags(false, strings.Split(globalFlags.Interactor, " ")) if err != nil { Fail(globalFlags.Xml, err, "Parse interator flags") } } if globalFlags.Xml { fmt.Println(XML_HEADER) } desktop, err := CreateDesktopIfNeeded(programFlags, interactorFlags) if err != nil { Fail(globalFlags.Xml, err, "Create desktop if needed") } loadLibrary, err := GetLoadLibraryIfNeeded(programFlags, interactorFlags) if err != nil { Fail(globalFlags.Xml, err, "Load library if needed") } var program, interactor *subprocess.Subprocess program, err = SetupSubprocess(programFlags, desktop, loadLibrary) if err != nil { Fail(globalFlags.Xml, err, "Setup main subprocess") } if interactorFlags != nil { interactor, err = SetupSubprocess(interactorFlags, desktop, loadLibrary) if err != nil { Fail(globalFlags.Xml, err, "Setup interactor subprocess") } var recordI, recordO *os.File if globalFlags.RecordProgramInput != "" { recordI, err = os.Create(globalFlags.RecordProgramInput) if err != nil { Fail(globalFlags.Xml, err, "Create input recorded") } } if globalFlags.RecordProgramOutput != "" { recordO, err = os.Create(globalFlags.RecordProgramOutput) if err != nil { Fail(globalFlags.Xml, err, "Create output recorder") } } err = subprocess.Interconnect(program, interactor, recordI, recordO) if err != nil { Fail(globalFlags.Xml, err, "Interconnect") } } cs := make(chan RunResult, 1) outstanding := 1 if interactor != nil { outstanding++ go ExecAndSend(interactor, cs, INTERACTOR) } go ExecAndSend(program, cs, PROGRAM) var results [2]*RunResult var programReturnCode int for outstanding > 0 { r := <-cs outstanding-- results[int(r.T)] = &r if r.T == PROGRAM && r.R != nil { programReturnCode = int(r.R.ExitCode) } } if globalFlags.Xml { fmt.Println(XML_RESULTS_START) } for _, result := range results { if result == nil { continue } PrintResult(globalFlags.Xml, globalFlags.ShowKernelModeTime, result) } if globalFlags.Xml { fmt.Println(XML_RESULTS_END) } if globalFlags.ReturnExitCode { os.Exit(programReturnCode) } }