0

Running an executable on a Windows command prompt along with the arguments is just fine:

cgx_STATIC.exe -b C:\Users\m3\AppData\Local\Temp\shot-277325955.fbd

But when running the same executable through Golang, the executable becomes non-responsive after some of the output files are created by the executable.


// Run an executable and print its log into a file.
func RunWithLogFile(pthExe string, arg []string, fLog *os.File) error {
    cmd := exec.Command(pthExe, arg...)

    stdout, err := cmd.StdoutPipe()
    if err != nil {
        return err
    }
    stderr, err := cmd.StderrPipe()
    if err != nil {
        return err
    }

    err = cmd.Start()
    if err != nil {
        return err
    }

    // Stream logs:
    // https://stackoverflow.com/a/48849811/3405291
    scannerOut := bufio.NewScanner(stdout)
    scannerErr := bufio.NewScanner(stderr)
    scannerOut.Split(bufio.ScanRunes)
    scannerErr.Split(bufio.ScanRunes)
    for scannerOut.Scan() {
        _, err = fLog.WriteString(scannerOut.Text())
        if err != nil {
            return err
        }
    }
    for scannerErr.Scan() {
        _, err = fLog.WriteString(scannerErr.Text())
        if err != nil {
            return err
        }
    }
    if scannerOut.Err() != nil {
        return err
    }
    if scannerErr.Err() != nil {
        return err
    }

    err = cmd.Wait()
    return err
}

I was wondering if the above Go code is somehow buggy or not suitable for running executables?

Separate goroutines

As suggested by @BurakSerdar I read from stdout and stderr in separate goroutines, but the problem didn't get resolved:


// Run an executable and print its log into a file.
func RunWithLogFile(pthExe string, arg []string, fLog *os.File) error {
    cmd := exec.Command(pthExe, arg...)

    stdout, err := cmd.StdoutPipe()
    if err != nil {
        return err
    }
    stderr, err := cmd.StderrPipe()
    if err != nil {
        return err
    }

    var wg sync.WaitGroup
    wg.Add(2)

    go streamToLogFile(stdout, fLog, &wg)
    go streamToLogFile(stderr, fLog, &wg)

    err = cmd.Start()
    if err != nil {
        return err
    }

    wg.Wait()

    err = cmd.Wait()
    return err
}

func streamToLogFile(output io.ReadCloser, fLog *os.File, wg *sync.WaitGroup) {
    defer wg.Done()
    scanner := bufio.NewScanner(output)
    scanner.Split(bufio.ScanRunes)
    for scanner.Scan() {
        _, err := fLog.WriteString(scanner.Text())
        if err != nil {
            log.Printf("error: write to log file: %s", err.Error())
        }
    }
    err := scanner.Err()
    if err != nil {
        log.Printf("error: write to log file: %s", err.Error())
    }
}
2
  • 1
    It might be waiting to write to stderr while you're expecting input from stdout. Read fro stdout and stderr in separate goroutines. Commented Sep 10, 2023 at 17:29
  • @BurakSerdar Right. The for loops look kind of suspicious. Commented Sep 10, 2023 at 19:51

2 Answers 2

0

The non-responsiveness was resolved by running the executable in batch mode. Studying the documentation:

But you need a graphic-capable computer because cgx needs it even if no graphic output is requested. Nevertheless the pop up of the graphic window can be suppressed by starting cgx with the -bg parameter. In this mode the performance is higher since no graphic related actions are performed.

So, running the executable with -bg resolved the problem.

UPDATE

The -bg parameter skips some features that I need. So, it couldn't help.

Sign up to request clarification or add additional context in comments.

Comments

0

The non-responsiveness was resolved by running the executable with admin privileges. I am doing this:

A C# code runs a Go code and the Go code runs a C Code, i.e. external executable.

The C executable calls some OpenGL GLUT calls. Maybe they need admin privileges.

The problem was resolved by C# launching the Go code like this: https://stackoverflow.com/a/2532775/3405291

        public static void RunLogic(string exePath, string args, PostProcess pp)
        {
            cmd = new Process();

            try
            {
                cmd.StartInfo.FileName = exePath;
                cmd.StartInfo.Arguments = args;
                cmd.StartInfo.UseShellExecute = true;
                cmd.StartInfo.CreateNoWindow = false;
                cmd.StartInfo.RedirectStandardOutput = false;
                cmd.StartInfo.RedirectStandardError = false;
                cmd.StartInfo.RedirectStandardInput = false;
                // Vista or higher check.
                // https://stackoverflow.com/a/2532775/3405291
                if (System.Environment.OSVersion.Version.Major >= 6)
                {
                    // Run with admin privileges to avoid a non-responsive executable.
                    cmd.StartInfo.Verb = "runas";
                }
                cmd.EnableRaisingEvents = true;
                cmd.Exited += new EventHandler(cmd_Exited);
                cmd.Exited += new EventHandler(pp);

                cmd.Start();
            }

            catch (Exception ex)
            {
                RhinoApp.WriteLine("Error on process start: {0}", ex.Message);
            }
        }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.