veyron/runtimes/google: adding AppCycle service implementation to the runtime.

We create a new server for this purpose, and hook things up to the task tracker
mechanism. This CL also ensures that the task tracking channels get closed when
the runtime shuts down (to indicate when the shutdown is imminent).

To faciliate conveying the child's app cycle service name to the parent, we
introduce a config API and a config service (which subsumes the previous
callback mechanism into a more general API). The new mechanics are as follows:
- parent sends a config to the child, part of which is the parent's config
service veyron name;
- the child's app manager calls the parent's config service to let the parent
know what its own veyron name is;
- (if the child is a node manager), it calls the parent's config service to let
the parent know what the child's node manager service veyron name is.
The newly introduced config API and config service will be folded with the
config neighborhood service into "the" veyron config API.

Change-Id: I1ff427ae77097b012aef138df1e6347bf6623e4a
diff --git a/lib/exec/child.go b/lib/exec/child.go
index 45b4a4d..287e521 100644
--- a/lib/exec/child.go
+++ b/lib/exec/child.go
@@ -6,6 +6,8 @@
 	"io"
 	"os"
 	"sync"
+
+	"veyron/lib/config"
 )
 
 var (
@@ -14,19 +16,15 @@
 )
 
 type ChildHandle struct {
-	// CallbackName is a callback name that can be use to notify the
-	// parent that the child has started up successfully via the
-	// Callback() RPC.
-	CallbackName string
+	// Config is passed down from the parent.
+	Config config.Config
 	// Secret is a secret passed to the child by its parent via a
 	// trusted channel.
 	Secret string
-	// statusPipe is a pipe that is used to notify the parent that the
-	// child process has started successfully. Unlike the Callback()
-	// RPC, which is to be invoked by the application to notify the
-	// parent that the application is "ready", the statusPipe is to be
-	// invoked by the veyron framework to notify the parent that the
-	// child process has successfully started.
+	// statusPipe is a pipe that is used to notify the parent that the child
+	// process has started successfully. It is meant to be invoked by the
+	// veyron framework to notify the parent that the child process has
+	// successfully started.
 	statusPipe *os.File
 }
 
@@ -84,18 +82,22 @@
 		return nil, ErrUnsupportedVersion
 	}
 	dataPipe := os.NewFile(3, "data_rd")
-	name, err := decodeString(dataPipe)
+	serializedConfig, err := decodeString(dataPipe)
 	if err != nil {
 		return nil, err
 	}
+	cfg := config.New()
+	if err := cfg.MergeFrom(serializedConfig); err != nil {
+		return nil, err
+	}
 	secret, err := decodeString(dataPipe)
 	if err != nil {
 		return nil, err
 	}
 	childHandle = &ChildHandle{
-		CallbackName: name,
-		Secret:       secret,
-		statusPipe:   os.NewFile(4, "status_wr"),
+		Config:     cfg,
+		Secret:     secret,
+		statusPipe: os.NewFile(4, "status_wr"),
 	}
 	return childHandle, nil
 }
diff --git a/lib/exec/doc.go b/lib/exec/doc.go
index ab4a6c0..f0b8168 100644
--- a/lib/exec/doc.go
+++ b/lib/exec/doc.go
@@ -1,5 +1,6 @@
 // Package exec implements simple process creation and rendezvous, including
-// sharing a secret with the newly created process.
+// sharing a secret with, and passing arbitrary configuration to, the newly
+// created process.
 //
 // Once a parent starts a child process it can use WaitForReady to wait
 // for the child to reach its 'Ready' state. Operations are provided to wait
@@ -11,5 +12,4 @@
 // goroutine to handle the process rendezvous. The child must call SetReady to
 // indicate that it is fully initialized and ready for whatever purpose it is
 // intended to fulfill.
-//
 package exec
diff --git a/lib/exec/exec_test.go b/lib/exec/exec_test.go
index 85edb87..47e19b7 100644
--- a/lib/exec/exec_test.go
+++ b/lib/exec/exec_test.go
@@ -10,6 +10,7 @@
 	"testing"
 	"time"
 
+	"veyron/lib/config"
 	vexec "veyron/lib/exec"
 	// Use mock timekeeper to avoid actually sleeping during the test.
 	"veyron/runtimes/google/testing/timekeeper"
@@ -99,19 +100,25 @@
 	panic("unreachable")
 }
 
-func TestCallbackNameExchange(t *testing.T) {
-	cmd := helperCommand("testCallbackName")
+func TestConfigExchange(t *testing.T) {
+	cmd := helperCommand("testConfig")
 	stderr, _ := cmd.StderrPipe()
-	ph := vexec.NewParentHandle(cmd, vexec.CallbackNameOpt("dummy_name"))
+	cfg := config.New()
+	cfg.Set("foo", "bar")
+	ph := vexec.NewParentHandle(cmd, vexec.ConfigOpt{cfg})
 	err := ph.Start()
 	if err != nil {
-		t.Fatalf("testCallbackNameTest: start: %v", err)
+		t.Fatalf("testConfig: start: %v", err)
 	}
-	if !expectMessage(stderr, "dummy_name") {
+	serialized, err := cfg.Serialize()
+	if err != nil {
+		t.Fatalf("testConfig: failed to serialize config: %v", err)
+	}
+	if !expectMessage(stderr, serialized) {
 		t.Errorf("unexpected output from child")
 	} else {
 		if err = cmd.Wait(); err != nil {
-			t.Errorf("testCallbackNameTest: wait: %v", err)
+			t.Errorf("testConfig: wait: %v", err)
 		}
 	}
 	clean(t, ph)
@@ -480,12 +487,16 @@
 		}()
 		r := <-rc
 		os.Exit(r)
-	case "testCallbackName":
+	case "testConfig":
 		ch, err := vexec.GetChildHandle()
 		if err != nil {
 			log.Fatalf("%v", err)
 		} else {
-			fmt.Fprintf(os.Stderr, "%s", ch.CallbackName)
+			serialized, err := ch.Config.Serialize()
+			if err != nil {
+				log.Fatalf("%v", err)
+			}
+			fmt.Fprintf(os.Stderr, "%s", serialized)
 		}
 	case "testSecret":
 		ch, err := vexec.GetChildHandle()
diff --git a/lib/exec/parent.go b/lib/exec/parent.go
index f3a185b..eecc198 100644
--- a/lib/exec/parent.go
+++ b/lib/exec/parent.go
@@ -9,6 +9,7 @@
 	"syscall"
 	"time"
 
+	"veyron/lib/config"
 	"veyron/lib/testutil/blackbox/parent"
 	// TODO(cnicolaou): move timekeeper out of runtimes
 	"veyron/runtimes/google/lib/timekeeper"
@@ -25,7 +26,7 @@
 // A ParentHandle is the Parent process' means of managing a single child.
 type ParentHandle struct {
 	c           *exec.Cmd
-	name        string
+	config      config.Config
 	secret      string
 	statusRead  *os.File
 	statusWrite *os.File
@@ -39,19 +40,21 @@
 	ExecParentHandleOpt()
 }
 
-// CallbackNameOpt can be used to seed the parent handle with a
-// custom callback name.
-type CallbackNameOpt string
+// ConfigOpt can be used to seed the parent handle with a
+// config to be passed to the child.
+type ConfigOpt struct {
+	config.Config
+}
 
-// ExecParentHandleOpt makes CallbackNameOpt an instance of
+// ExecParentHandleOpt makes ConfigOpt an instance of
 // ParentHandleOpt.
-func (cno CallbackNameOpt) ExecParentHandleOpt() {}
+func (ConfigOpt) ExecParentHandleOpt() {}
 
 // SecretOpt can be used to seed the parent handle with a custom secret.
 type SecretOpt string
 
 // ExecParentHandleOpt makes SecretOpt an instance of ParentHandleOpt.
-func (so SecretOpt) ExecParentHandleOpt() {}
+func (SecretOpt) ExecParentHandleOpt() {}
 
 // TimeKeeperOpt can be used to seed the parent handle with a custom timekeeper.
 type TimeKeeperOpt struct {
@@ -59,18 +62,18 @@
 }
 
 // ExecParentHandleOpt makes TimeKeeperOpt an instance of ParentHandleOpt.
-func (tko TimeKeeperOpt) ExecParentHandleOpt() {}
+func (TimeKeeperOpt) ExecParentHandleOpt() {}
 
 // NewParentHandle creates a ParentHandle for the child process represented by
 // an instance of exec.Cmd.
 func NewParentHandle(c *exec.Cmd, opts ...ParentHandleOpt) *ParentHandle {
 	c.Env = append(c.Env, versionVariable+"="+version1)
-	name, secret := "", ""
+	cfg, secret := config.New(), ""
 	tk := timekeeper.RealTime()
 	for _, opt := range opts {
 		switch v := opt.(type) {
-		case CallbackNameOpt:
-			name = string(v)
+		case ConfigOpt:
+			cfg = v
 		case SecretOpt:
 			secret = string(v)
 		case TimeKeeperOpt:
@@ -81,7 +84,7 @@
 	}
 	return &ParentHandle{
 		c:      c,
-		name:   name,
+		config: cfg,
 		secret: secret,
 		tk:     tk,
 	}
@@ -125,7 +128,11 @@
 		return err
 	}
 	// Pass data to the child using a pipe.
-	if err := encodeString(dataWrite, p.name); err != nil {
+	serializedConfig, err := p.config.Serialize()
+	if err != nil {
+		return err
+	}
+	if err := encodeString(dataWrite, serializedConfig); err != nil {
 		p.statusWrite.Close()
 		p.statusRead.Close()
 		return err