dajood
dajood

Reputation: 4050

How to start a process?

I try to start a JVM out of a Google Go program that looks like this:

package main
import "fmt"
import "os"
import "log"
func main() {

var name string
name="\\jrex64\\bin\\java.exe"

var path="-Xbootclasspath:jrex64\\lib\\rt.jar;"+
"jrex64\\lib\\jfxrt.jar;"+
"jrex64\\lib\\resources.jar;"+
"jrex64\\lib\\ext\\sunjce_provider.jar;"+
"jrex64\\lib\\ext\\zipfs.jar;"+
"jrex64\\lib\\ext\\sunmscapi.jar;"+
"jrex64\\lib\\ext\\sunec.jar;"+
"jrex64\\lib\\ext\\dnsns.jar;"+
"jrex64\\lib\\ext\\access-bridge-64.jar;"+
"jrex64\\lib\\security\\local_policy.jar;"+
"jrex64\\lib\\jce.jar;"+
"jrex64\\lib\\jfr.jar;"+
"jrex64\\lib\\jsse.jar;"+
"jrex64\\lib\\charsets.jar;"+
"jrex64\\lib\\";



var args[] string=make([]string,4)
args[0]="-verbose"
args[1]=path;
args[2]="-cp Ganesha_lib\\*"
args[3]="-jar Ganesha.jar"

var attr* os.ProcAttr

proc,err:=os.StartProcess(name,args,attr)
proc.Wait();


if err!=nil {
    fmt.Println("an error occurred.\n")
    log.Fatal(err)
}

}

It's my first Go program. And i'm totally overwhelmed by getting the following error:

panic: runtime error: invalid memory address or nil pointer dereference [signal 0xc0000005 code=0x0 addr=0x0 pc=0x4278b5] goroutine 1 [running]: os.startProcess(0x4aacb4, 0x14, 0xf840001eb0, 0x500000005, 0x0, ...) C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist767862039/go/src/pkg/os/exec_posix.go:28 +0x152 os.StartProcess(0x4aacb4, 0x14, 0xf840001eb0, 0x500000005, 0x0, ...) C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist767862039/go/src/pkg/os/doc.go:24 +0x5c main.main() D:/MyGoProject/src/main.go:60 +0x23c goroutine 2 [syscall]: created by runtime.main C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist767862039/go/src/pkg/runtime/proc.c:221 Process finished with exit code 2

How do i have to interpret this error code? What went wrong? And how can i get the JVM startet - it's situated in a subdirectory of the Go executable file.

Upvotes: 14

Views: 18983

Answers (4)

On Windows, os.ProcAttr cannot be left empty. At Dir must be set to an empty string and Sys must be set to &syscall.SysProcAttr{}. The following should work:

name := "\\jrex64\\bin\\java.exe"
libs := "-Xbootclasspath:jrex64\\lib\\rt.jar;" +
    // add all libs
    "jrex64\\lib\\";
args := []string{"-verbose", libs, "-cp Ganesha_lib\\*", "-jar Ganesha.jar"}
attr := &os.ProcAttr{
    "",
    nil,
    []*os.File{os.Stdin, os.Stdout, os.Stderr},
    &syscall.SysProcAttr{}} //CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP, } 
}

proc, err := os.StartProcess(name,args,attr);
if err != nil {
    log.Fatalf("start process: %v", err)
}
_, err = proc.Wait();
if err != nil {
    log.Fatalf("wait: %v", err)
}

Upvotes: 2

David Tootill
David Tootill

Reputation: 571

The previous answers don't actually describe how to use os.StartProcess(). Here's an example:

cmdToRun := "/path/to/someCommand"
args := []string{"someCommand", "arg1"}
procAttr := new(os.ProcAttr)
procAttr.Files = []*os.File{os.Stdin, os.Stdout, os.Stderr}
if process, err := os.StartProcess(cmdToRun, args, procAttr); err != nil {
    fmt.Printf("ERROR Unable to run %s: %s\n", cmdToRun, err.Error())
} else {
    fmt.Printf("%s running as pid %d\n", cmdToRun, process.Pid)
}

Note that it's necessary to initialize the ProcAttr.Files field - if you don't, you may get an index out of bounds error deep in the os package. You can use pipes for the files if you want to provide input or process output from the new process in your own code. You may also want to specify the Dir (starting directory) and Env (environment variables) fields.

Upvotes: 16

Stephen Weinberg
Stephen Weinberg

Reputation: 53418

It is normally recommended you don't use os.StartProcess directly. Instead, use os/exec which has a much easier interface. Here is how I would start a java subprocess and wait for it to complete.

http://play.golang.org/p/APlp9KK9wx

package main

import (
    "fmt"
    "log"
    "os/exec"
    "strings"
)

func main() {
    var java = "\\jrex64\\bin\\java.exe"

    var path = []string{
        "jrex64\\lib\\rt.jar",
        "jrex64\\lib\\jfxrt.jar",
        "jrex64\\lib\\resources.jar",
        "jrex64\\lib\\ext\\sunjce_provider.jar",
        "jrex64\\lib\\ext\\zipfs.jar",
        "jrex64\\lib\\ext\\sunmscapi.jar",
        "jrex64\\lib\\ext\\sunec.jar",
        "jrex64\\lib\\ext\\dnsns.jar",
        "jrex64\\lib\\ext\\access-bridge-64.jar",
        "jrex64\\lib\\security\\local_policy.jar",
        "jrex64\\lib\\jce.jar",
        "jrex64\\lib\\jfr.jar",
        "jrex64\\lib\\jsse.jar",
        "jrex64\\lib\\charsets.jar",
        "jrex64\\lib\\",
    }

    pathflag := "-Xbootclasspath:" + strings.Join(path, ";")
    cmd := exec.Command(java, "-verbose", pathflag, "-cp Ganesha_lib\\*", "-jar Ganesha.jar")
    err := cmd.Run()

    if err != nil {
        fmt.Println("an error occurred.\n")
        log.Fatal(err)
    }

}

In case you are curious, the reason you got that panic was that attr is a nil pointer. Instead, you could have done attr := new(os.ProcAttr).

Upvotes: 20

zzzz
zzzz

Reputation: 91253

Here:

var attr* os.ProcAttr

proc, err := os.StartProcess(name, args, attr)

The attr variable is nil and when dereferenced in os.StartProcess it causes the error you see.

Upvotes: 3

Related Questions