From 9ae1a64c385dbf919a389d841af271996e4b705c Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sun, 1 Sep 2013 11:37:09 -0700 Subject: [PATCH] devcam: exec child binaries when possible Change-Id: I56d56d9f7416e3d5958e736762063a48dcd8e9f9 --- dev/devcam/appengine.go | 10 +--------- dev/devcam/camget.go | 9 +-------- dev/devcam/camput.go | 9 +-------- dev/devcam/devcam.go | 21 +++++++++++++++++++++ dev/devcam/exec.go | 27 +++++++++++++++++++++++++++ dev/devcam/server.go | 10 ++-------- 6 files changed, 53 insertions(+), 33 deletions(-) create mode 100644 dev/devcam/exec.go diff --git a/dev/devcam/appengine.go b/dev/devcam/appengine.go index 3276a6323..9635711f5 100644 --- a/dev/devcam/appengine.go +++ b/dev/devcam/appengine.go @@ -95,15 +95,7 @@ func (c *gaeCmd) RunCommand(args []string) error { } cmdArgs = append(cmdArgs, args...) cmdArgs = append(cmdArgs, c.applicationDir) - cmd := exec.Command(devAppServerBin, cmdArgs...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Start(); err != nil { - return fmt.Errorf("Could not start dev_appserver.py: %v", err) - } - go handleSignals(cmd.Process) - cmd.Wait() - return nil + return runExec(devAppServerBin, cmdArgs) } func (c *gaeCmd) checkFlags(args []string) error { diff --git a/dev/devcam/camget.go b/dev/devcam/camget.go index 50d18b62d..77bfe4b1f 100644 --- a/dev/devcam/camget.go +++ b/dev/devcam/camget.go @@ -99,14 +99,7 @@ func (c *getCmd) RunCommand(args []string) error { cmdArgs = append(cmdArgs, "-server="+blobserver) } cmdArgs = append(cmdArgs, args...) - cmd := exec.Command(cmdBin, cmdArgs...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Start(); err != nil { - return fmt.Errorf("Could not run camget: %v", err) - } - go handleSignals(cmd.Process) - return cmd.Wait() + return runExec(cmdBin, cmdArgs) } func (c *getCmd) checkFlags(args []string) error { diff --git a/dev/devcam/camput.go b/dev/devcam/camput.go index bbdeb705a..e4ed409c9 100644 --- a/dev/devcam/camput.go +++ b/dev/devcam/camput.go @@ -98,14 +98,7 @@ func (c *putCmd) RunCommand(args []string) error { "-server=" + blobserver, } cmdArgs = append(cmdArgs, args...) - cmd := exec.Command(cmdBin, cmdArgs...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Start(); err != nil { - return fmt.Errorf("Could not run camput: %v", err) - } - go handleSignals(cmd.Process) - return cmd.Wait() + return runExec(cmdBin, cmdArgs) } func (c *putCmd) checkFlags(args []string) error { diff --git a/dev/devcam/devcam.go b/dev/devcam/devcam.go index 1da95ec0b..31deefa03 100644 --- a/dev/devcam/devcam.go +++ b/dev/devcam/devcam.go @@ -21,6 +21,7 @@ import ( "io" "log" "os" + "os/exec" "os/signal" "path/filepath" "strings" @@ -29,6 +30,26 @@ import ( "camlistore.org/pkg/cmdmain" ) +// sysExec is set to syscall.Exec on platforms that support it. +var sysExec func(argv0 string, argv []string, envv []string) (err error) + +// runExec execs bin. If the platform doesn't support exec, it runs it and waits +// for it to finish. +func runExec(bin string, args []string) error { + if sysExec != nil { + sysExec(bin, append([]string{filepath.Base(bin)}, args...), os.Environ()) + } + + cmd := exec.Command(bin, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Start(); err != nil { + return fmt.Errorf("Could not run camput: %v", err) + } + go handleSignals(cmd.Process) + return cmd.Wait() +} + func setenv(key, value string) { err := os.Setenv(key, value) if err != nil { diff --git a/dev/devcam/exec.go b/dev/devcam/exec.go new file mode 100644 index 000000000..f62ee1536 --- /dev/null +++ b/dev/devcam/exec.go @@ -0,0 +1,27 @@ +// +build !windows + +/* +Copyright 2013 The Camlistore Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "syscall" +) + +func init() { + sysExec = syscall.Exec +} diff --git a/dev/devcam/server.go b/dev/devcam/server.go index a0f983827..8da054ccf 100644 --- a/dev/devcam/server.go +++ b/dev/devcam/server.go @@ -383,13 +383,7 @@ func (c *serverCmd) RunCommand(args []string) error { cmdArgs := []string{ "-configfile=" + filepath.Join(c.camliSrcRoot, "config", "dev-server-config.json"), "-listen=" + c.listen, - "-openbrowser=" + strconv.FormatBool(c.openBrowser)} - cmd := exec.Command(camliBin, cmdArgs...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Start(); err != nil { - return fmt.Errorf("Could not start camlistored: %v", err) + "-openbrowser=" + strconv.FormatBool(c.openBrowser), } - go handleSignals(cmd.Process) - return cmd.Wait() + return runExec(camliBin, cmdArgs) }