Merge "Fix flaky TestNoServersAvailable"
diff --git a/lib/modules/examples_test.go b/lib/modules/examples_test.go
new file mode 100644
index 0000000..2247b7a
--- /dev/null
+++ b/lib/modules/examples_test.go
@@ -0,0 +1,52 @@
+package modules_test
+
+import (
+ "fmt"
+ "io"
+ "os"
+
+ "veyron.io/veyron/veyron/lib/modules"
+)
+
+func init() {
+ modules.RegisterChild("echo", "<args>...", echo)
+}
+
+func echo(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+ for i, a := range args {
+ fmt.Fprintf(stdout, "%d: %s\n", i, a)
+ }
+ return nil
+}
+
+func ExampleDispatch() {
+ if modules.IsModulesProcess() {
+ // Child process. Dispatch will invoke the 'echo' command
+ if err := modules.Dispatch(); err != nil {
+ panic(fmt.Sprintf("unexpected error: %s", err))
+ }
+ return
+ }
+ // Parent process.
+ sh, _ := modules.NewShell(nil)
+ defer sh.Cleanup(nil, nil)
+ h, _ := sh.Start("echo", nil, "a", "b")
+ h.Shutdown(os.Stdout, os.Stderr)
+ // Output:
+ // 0: echo
+ // 1: a
+ // 2: b
+}
+
+func ExampleDispatchAndExit() {
+ // DispatchAndExit will call os.Exit(0) when executed within the child.
+ modules.DispatchAndExit()
+ sh, _ := modules.NewShell(nil)
+ defer sh.Cleanup(nil, nil)
+ h, _ := sh.Start("echo", nil, "c", "d")
+ h.Shutdown(os.Stdout, os.Stderr)
+ // Output:
+ // 0: echo
+ // 1: c
+ // 2: d
+}
diff --git a/lib/modules/registry.go b/lib/modules/registry.go
index 61325d2..721e45a 100644
--- a/lib/modules/registry.go
+++ b/lib/modules/registry.go
@@ -115,6 +115,16 @@
// a subprocess that is not a unit test. It will return without an error
// if it is executed by a process that does not specify an entry point
// in its environment.
+//
+// func main() {
+// if modules.IsModulesProcess() {
+// if err := modules.Dispatch(); err != nil {
+// panic("error")
+// }
+// return
+// }
+// parent code...
+//
func Dispatch() error {
if !IsModulesProcess() {
return nil
@@ -125,6 +135,27 @@
return registry.dispatch()
}
+// DispatchAndExit is like Dispatch except that it will call os.Exit(0)
+// when executed within a child process and the command succeeds, or panic
+// on encountering an error.
+//
+// func main() {
+// modules.DispatchAndExit()
+// parent code...
+//
+func DispatchAndExit() {
+ if !IsModulesProcess() {
+ return
+ }
+ if IsTestHelperProcess() {
+ panic("use DispatchInTest in unittests")
+ }
+ if err := registry.dispatch(); err != nil {
+ panic(fmt.Sprintf("unexpected error: %s", err))
+ }
+ os.Exit(0)
+}
+
func (r *cmdRegistry) dispatch() error {
ch, err := vexec.GetChildHandle()
if err != nil {