You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2017/04/03 23:53:58 UTC

[1/6] incubator-mynewt-newtmgr git commit: newtmgr - pretty print ~/.newtmgr.cp.json file.

Repository: incubator-mynewt-newtmgr
Updated Branches:
  refs/heads/master ff255cbfa -> 7f57aa2d4


newtmgr - pretty print ~/.newtmgr.cp.json file.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/commit/0384fcf0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/tree/0384fcf0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/diff/0384fcf0

Branch: refs/heads/master
Commit: 0384fcf0bf64659c7c0cd7b2b9bfa20adaf4ec57
Parents: ff255cb
Author: Christopher Collins <cc...@apache.org>
Authored: Thu Mar 30 10:01:52 2017 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Thu Mar 30 10:01:52 2017 -0700

----------------------------------------------------------------------
 newtmgr/config/connprofile.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/0384fcf0/newtmgr/config/connprofile.go
----------------------------------------------------------------------
diff --git a/newtmgr/config/connprofile.go b/newtmgr/config/connprofile.go
index 0ca4cc8..da69695 100644
--- a/newtmgr/config/connprofile.go
+++ b/newtmgr/config/connprofile.go
@@ -177,7 +177,7 @@ func (cpm *ConnProfileMgr) GetConnProfileList() ([]*ConnProfile, error) {
 
 func (cpm *ConnProfileMgr) save() error {
 	list, _ := cpm.GetConnProfileList()
-	b, err := json.Marshal(list)
+	b, err := json.MarshalIndent(list, "", "    ")
 	if err != nil {
 		return util.NewNewtError(err.Error())
 	}


[3/6] incubator-mynewt-newtmgr git commit: nmxact - Automatically restart BLE xport.

Posted by cc...@apache.org.
nmxact - Automatically restart BLE xport.

More work needs to be done here.  If a client attempts to use the
transport while it is restarting, the attempt immediately fails.

It would be better if:
    * The transmit attempt blocks until the transport is done
      restarting.
    * The transport gives up after X consecutive failures.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/commit/2aeb4daa
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/tree/2aeb4daa
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/diff/2aeb4daa

Branch: refs/heads/master
Commit: 2aeb4daab6e2a13152314c23cd1c79fed5ebbdd2
Parents: db639f9
Author: Christopher Collins <cc...@apache.org>
Authored: Mon Apr 3 16:38:03 2017 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Mon Apr 3 16:49:58 2017 -0700

----------------------------------------------------------------------
 nmxact/nmble/ble_xport.go | 167 +++++++++++++++++++++++++++++++----------
 nmxact/nmble/dispatch.go  |  15 ++++
 2 files changed, 144 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/2aeb4daa/nmxact/nmble/ble_xport.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_xport.go b/nmxact/nmble/ble_xport.go
index 16a4128..32ced04 100644
--- a/nmxact/nmble/ble_xport.go
+++ b/nmxact/nmble/ble_xport.go
@@ -53,21 +53,26 @@ const (
 	BLE_XPORT_STATE_STOPPED BleXportState = iota
 	BLE_XPORT_STATE_STARTING
 	BLE_XPORT_STATE_STARTED
+	BLE_XPORT_STATE_STOPPING
 )
 
 // Implements xport.Xport.
 type BleXport struct {
-	Bd     *BleDispatcher
-	client *unixchild.Client
-	state  BleXportState
+	Bd               *BleDispatcher
+	client           *unixchild.Client
+	state            BleXportState
+	stopChan         chan struct{}
+	shutdownChan     chan bool
+	numStopListeners int
 
 	cfg XportCfg
 }
 
 func NewBleXport(cfg XportCfg) (*BleXport, error) {
 	bx := &BleXport{
-		Bd:  NewBleDispatcher(),
-		cfg: cfg,
+		Bd:           NewBleDispatcher(),
+		shutdownChan: make(chan bool),
+		cfg:          cfg,
 	}
 
 	return bx, nil
@@ -177,18 +182,46 @@ func (bx *BleXport) initialSyncCheck() (bool, *BleListener, error) {
 	return synced, bl, nil
 }
 
-func (bx *BleXport) onError(err error) {
-	if !bx.setStateFrom(BLE_XPORT_STATE_STARTED, BLE_XPORT_STATE_STOPPED) &&
-		!bx.setStateFrom(BLE_XPORT_STATE_STARTING, BLE_XPORT_STATE_STOPPED) {
+func (bx *BleXport) shutdown(restart bool, err error) {
+	var fullyStarted bool
 
+	if bx.setStateFrom(BLE_XPORT_STATE_STARTED,
+		BLE_XPORT_STATE_STOPPING) {
+
+		fullyStarted = true
+	} else if bx.setStateFrom(BLE_XPORT_STATE_STARTING,
+		BLE_XPORT_STATE_STOPPING) {
+
+		fullyStarted = false
+	} else {
 		// Stop already in progress.
 		return
 	}
+
+	// Stop the unixchild instance (blehostd + socket).
 	if bx.client != nil {
 		bx.client.Stop()
+
+		// Unblock the unixchild instance.
 		bx.client.FromChild <- nil
 	}
+
+	// Indicate an error to all of this transport's listeners.  This prevents
+	// them from blocking endlessly while awaiting a BLE message.
 	bx.Bd.ErrorAll(err)
+
+	// Stop all of this transport's go routines.
+	for i := 0; i < bx.numStopListeners; i++ {
+		bx.stopChan <- struct{}{}
+	}
+
+	bx.setStateFrom(BLE_XPORT_STATE_STOPPING, BLE_XPORT_STATE_STOPPED)
+
+	// Indicate that the shutdown is complete.  If restarts are enabled on this
+	// transport, this signals that the transport should be started again.
+	if fullyStarted {
+		bx.shutdownChan <- restart
+	}
 }
 
 func (bx *BleXport) setStateFrom(from BleXportState, to BleXportState) bool {
@@ -202,47 +235,68 @@ func (bx *BleXport) getState() BleXportState {
 }
 
 func (bx *BleXport) Stop() error {
-	bx.onError(nil)
+	bx.shutdown(false, nil)
 	return nil
 }
 
-func (bx *BleXport) Start() error {
+func (bx *BleXport) startOnce() error {
 	if !bx.setStateFrom(BLE_XPORT_STATE_STOPPED, BLE_XPORT_STATE_STARTING) {
 		return nmxutil.NewXportError("BLE xport started twice")
 	}
 
+	bx.stopChan = make(chan struct{})
+	bx.numStopListeners = 0
+	bx.Bd.Clear()
+
 	bx.createUnixChild()
 	if err := bx.client.Start(); err != nil {
 		if unixchild.IsUcAcceptError(err) {
-			err = nmxutil.NewXportError("blehostd did not connect to socket; " +
-				"controller not attached?")
+			err = nmxutil.NewXportError(
+				"blehostd did not connect to socket; " +
+					"controller not attached?")
 		} else {
+			panic(err.Error())
 			err = nmxutil.NewXportError(
 				"Failed to start child process: " + err.Error())
 		}
-		bx.setStateFrom(BLE_XPORT_STATE_STARTING, BLE_XPORT_STATE_STOPPED)
+		bx.shutdown(true, err)
 		return err
 	}
 
 	go func() {
-		err := <-bx.client.ErrChild
-		err = nmxutil.NewXportError("BLE transport error: " + err.Error())
-		fmt.Printf("%s\n", err.Error())
-		bx.onError(err)
+		bx.numStopListeners++
+		for {
+			select {
+			case err := <-bx.client.ErrChild:
+				err = nmxutil.NewXportError("BLE transport error: " +
+					err.Error())
+				go bx.shutdown(true, err)
+
+			case <-bx.stopChan:
+				return
+			}
+		}
 	}()
 
 	go func() {
+		bx.numStopListeners++
 		for {
-			if b := bx.rx(); b == nil {
-				// The error should have been reported to everyone interested.
-				break
+			select {
+			case buf := <-bx.client.FromChild:
+				if len(buf) != 0 {
+					log.Debugf("Receive from blehostd:\n%s", hex.Dump(buf))
+					bx.Bd.Dispatch(buf)
+				}
+
+			case <-bx.stopChan:
+				return
 			}
 		}
 	}()
 
 	synced, bl, err := bx.initialSyncCheck()
 	if err != nil {
-		bx.Stop()
+		bx.shutdown(true, err)
 		return err
 	}
 
@@ -253,6 +307,7 @@ func (bx *BleXport) Start() error {
 		for {
 			select {
 			case err := <-bl.ErrChan:
+				bx.shutdown(true, err)
 				return err
 			case bm := <-bl.BleChan:
 				switch msg := bm.(type) {
@@ -262,34 +317,37 @@ func (bx *BleXport) Start() error {
 					}
 				}
 			case <-time.After(bx.cfg.SyncTimeout):
-				bx.Stop()
-				return nmxutil.NewXportError(
+				err := nmxutil.NewXportError(
 					"Timeout waiting for host <-> controller sync")
+				bx.shutdown(true, err)
+				return err
 			}
 		}
 	}
 
 	// Host and controller are synced.  Listen for sync loss in the background.
 	go func() {
+		bx.numStopListeners++
 		for {
 			select {
 			case err := <-bl.ErrChan:
-				bx.onError(err)
-				return
+				go bx.shutdown(true, err)
 			case bm := <-bl.BleChan:
 				switch msg := bm.(type) {
 				case *BleSyncEvt:
 					if !msg.Synced {
-						bx.onError(nmxutil.NewXportError(
+						go bx.shutdown(true, nmxutil.NewXportError(
 							"BLE host <-> controller sync lost"))
-						return
 					}
 				}
+			case <-bx.stopChan:
+				return
 			}
 		}
 	}()
 
 	if !bx.setStateFrom(BLE_XPORT_STATE_STARTING, BLE_XPORT_STATE_STARTED) {
+		bx.shutdown(true, err)
 		return nmxutil.NewXportError(
 			"Internal error; BLE transport in unexpected state")
 	}
@@ -297,6 +355,47 @@ func (bx *BleXport) Start() error {
 	return nil
 }
 
+func (bx *BleXport) Start() error {
+	// Try to start the transport.  If this first attempt fails, report the
+	// error and don't retry.
+	if err := bx.startOnce(); err != nil {
+		log.Debugf("Error starting BLE transport: %s",
+			err.Error())
+		return err
+	}
+
+	// Now that the first start attempt has succeeded, start a restart loop in
+	// the background.
+	go func() {
+		// Block until transport shuts down.
+		restart := <-bx.shutdownChan
+		for {
+			// If restarts are disabled, or if the shutdown was a result of an
+			// explicit stop call (instead of an unexpected error), stop
+			// restarting the transport.
+			if !bx.cfg.BlehostdRestart || !restart {
+				break
+			}
+
+			// Wait a second before the next restart.  This is necessary to
+			// ensure the unix domain socket can be rebound.
+			time.Sleep(time.Second)
+
+			// Attempt to start the transport again.
+			if err := bx.startOnce(); err != nil {
+				// Start attempt failed.
+				log.Debugf("Error starting BLE transport: %s",
+					err.Error())
+			} else {
+				// Success.  Block until the transport shuts down.
+				restart = <-bx.shutdownChan
+			}
+		}
+	}()
+
+	return nil
+}
+
 func (bx *BleXport) txNoSync(data []byte) {
 	log.Debugf("Tx to blehostd:\n%s", hex.Dump(data))
 	bx.client.ToChild <- data
@@ -304,23 +403,15 @@ func (bx *BleXport) txNoSync(data []byte) {
 
 func (bx *BleXport) Tx(data []byte) error {
 	if bx.getState() != BLE_XPORT_STATE_STARTED {
-		return nmxutil.NewXportError("Attempt to transmit before BLE xport " +
-			"fully started")
+		return nmxutil.NewXportError(
+			fmt.Sprintf("Attempt to transmit before BLE xport fully started; "+
+				"state=%d", bx.getState()))
 	}
 
 	bx.txNoSync(data)
 	return nil
 }
 
-func (bx *BleXport) rx() []byte {
-	buf := <-bx.client.FromChild
-	if len(buf) != 0 {
-		log.Debugf("Receive from blehostd:\n%s", hex.Dump(buf))
-		bx.Bd.Dispatch(buf)
-	}
-	return buf
-}
-
 func (bx *BleXport) RspTimeout() time.Duration {
 	return bx.cfg.BlehostdRspTimeout
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/2aeb4daa/nmxact/nmble/dispatch.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/dispatch.go b/nmxact/nmble/dispatch.go
index 546fc11..c9ef39e 100644
--- a/nmxact/nmble/dispatch.go
+++ b/nmxact/nmble/dispatch.go
@@ -267,7 +267,10 @@ func (bd *BleDispatcher) Dispatch(data []byte) {
 		return
 	}
 
+	bd.mutex.Lock()
 	_, listener := bd.findListener(base)
+	bd.mutex.Unlock()
+
 	if listener == nil {
 		log.Debugf(
 			"No BLE listener for op=%d type=%d seq=%d connHandle=%d",
@@ -295,3 +298,15 @@ func (bd *BleDispatcher) ErrorAll(err error) {
 		listener.ErrChan <- err
 	}
 }
+
+func (bd *BleDispatcher) Clear() {
+	bd.mutex.Lock()
+	defer bd.mutex.Unlock()
+
+	for s, _ := range bd.seqMap {
+		delete(bd.seqMap, s)
+	}
+	for b, _ := range bd.baseMap {
+		delete(bd.baseMap, b)
+	}
+}


[6/6] incubator-mynewt-newtmgr git commit: newtmgr - revendor

Posted by cc...@apache.org.
newtmgr - revendor


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/commit/7f57aa2d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/tree/7f57aa2d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/diff/7f57aa2d

Branch: refs/heads/master
Commit: 7f57aa2d4cce2af44b9cce2fcaaadafefcf6e391
Parents: d7b0a1a
Author: Christopher Collins <cc...@apache.org>
Authored: Fri Mar 31 15:56:33 2017 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Mon Apr 3 16:52:30 2017 -0700

----------------------------------------------------------------------
 newtmgr/Godeps/Godeps.json                      |  52 ++---
 .../newt/util/unixchild/unixchild.go            | 130 ++++-------
 .../newtmgr/nmxact/nmble/ble_act.go             |  16 +-
 .../newtmgr/nmxact/nmble/ble_fsm.go             |  53 +++--
 .../newtmgr/nmxact/nmble/ble_oic_sesn.go        |  12 +
 .../newtmgr/nmxact/nmble/ble_plain_sesn.go      |   6 +
 .../newtmgr/nmxact/nmble/ble_xport.go           | 220 ++++++++++++++-----
 .../newtmgr/nmxact/nmble/dispatch.go            |  15 ++
 .../newtmgr/nmxact/nmp/dispatch.go              |   1 +
 .../newtmgr/nmxact/sesn/sesn.go                 |   7 +
 .../newtmgr/nmxact/xact/cmd.go                  |   6 +
 .../newtmgr/nmxact/xact/config.go               |   8 +-
 .../newtmgr/nmxact/xact/crash.go                |   4 +-
 .../newtmgr/nmxact/xact/datetime.go             |   8 +-
 .../newtmgr/nmxact/xact/echo.go                 |   4 +-
 .../mynewt.apache.org/newtmgr/nmxact/xact/fs.go |   8 +-
 .../newtmgr/nmxact/xact/image.go                |  24 +-
 .../newtmgr/nmxact/xact/log.go                  |  20 +-
 .../newtmgr/nmxact/xact/mpstat.go               |   4 +-
 .../newtmgr/nmxact/xact/reset.go                |   4 +-
 .../newtmgr/nmxact/xact/run.go                  |   8 +-
 .../newtmgr/nmxact/xact/stat.go                 |   8 +-
 .../newtmgr/nmxact/xact/taskstat.go             |   4 +-
 23 files changed, 389 insertions(+), 233 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/Godeps/Godeps.json
----------------------------------------------------------------------
diff --git a/newtmgr/Godeps/Godeps.json b/newtmgr/Godeps/Godeps.json
index 4461c33..22eb507 100644
--- a/newtmgr/Godeps/Godeps.json
+++ b/newtmgr/Godeps/Godeps.json
@@ -76,68 +76,68 @@
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newt/util",
-			"Comment": "mynewt_1_0_0_b1_tag-208-g150c666",
-			"Rev": "150c6666bab17ce5a5805c1eda8a223d88cd109e"
+			"Comment": "mynewt_1_0_0_b1_tag-159-g66f1181",
+			"Rev": "66f118133159619cf027c8e9907173b6860c106e"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newt/util/unixchild",
-			"Comment": "mynewt_1_0_0_b1_tag-208-g150c666",
-			"Rev": "150c6666bab17ce5a5805c1eda8a223d88cd109e"
+			"Comment": "mynewt_1_0_0_b1_tag-159-g66f1181",
+			"Rev": "66f118133159619cf027c8e9907173b6860c106e"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newt/viper",
-			"Comment": "mynewt_1_0_0_b1_tag-208-g150c666",
-			"Rev": "150c6666bab17ce5a5805c1eda8a223d88cd109e"
+			"Comment": "mynewt_1_0_0_b1_tag-159-g66f1181",
+			"Rev": "66f118133159619cf027c8e9907173b6860c106e"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newt/yaml",
-			"Comment": "mynewt_1_0_0_b1_tag-208-g150c666",
-			"Rev": "150c6666bab17ce5a5805c1eda8a223d88cd109e"
+			"Comment": "mynewt_1_0_0_b1_tag-159-g66f1181",
+			"Rev": "66f118133159619cf027c8e9907173b6860c106e"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/bledefs",
-			"Comment": "mynewt_0_9_0_tag-448-ga808bde",
-			"Rev": "a808bde2b242416e3ad2e52d125fa26f098dc6e1"
+			"Comment": "mynewt_0_9_0_tag-454-gd3462c4",
+			"Rev": "d3462c4a6b00592a47e39b0bee3935e94a287038"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/nmble",
-			"Comment": "mynewt_0_9_0_tag-448-ga808bde",
-			"Rev": "a808bde2b242416e3ad2e52d125fa26f098dc6e1"
+			"Comment": "mynewt_0_9_0_tag-454-gd3462c4",
+			"Rev": "d3462c4a6b00592a47e39b0bee3935e94a287038"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/nmp",
-			"Comment": "mynewt_0_9_0_tag-448-ga808bde",
-			"Rev": "a808bde2b242416e3ad2e52d125fa26f098dc6e1"
+			"Comment": "mynewt_0_9_0_tag-454-gd3462c4",
+			"Rev": "d3462c4a6b00592a47e39b0bee3935e94a287038"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/nmserial",
-			"Comment": "mynewt_0_9_0_tag-448-ga808bde",
-			"Rev": "a808bde2b242416e3ad2e52d125fa26f098dc6e1"
+			"Comment": "mynewt_0_9_0_tag-454-gd3462c4",
+			"Rev": "d3462c4a6b00592a47e39b0bee3935e94a287038"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/nmxutil",
-			"Comment": "mynewt_0_9_0_tag-448-ga808bde",
-			"Rev": "a808bde2b242416e3ad2e52d125fa26f098dc6e1"
+			"Comment": "mynewt_0_9_0_tag-454-gd3462c4",
+			"Rev": "d3462c4a6b00592a47e39b0bee3935e94a287038"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/omp",
-			"Comment": "mynewt_0_9_0_tag-448-ga808bde",
-			"Rev": "a808bde2b242416e3ad2e52d125fa26f098dc6e1"
+			"Comment": "mynewt_0_9_0_tag-454-gd3462c4",
+			"Rev": "d3462c4a6b00592a47e39b0bee3935e94a287038"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/sesn",
-			"Comment": "mynewt_0_9_0_tag-448-ga808bde",
-			"Rev": "a808bde2b242416e3ad2e52d125fa26f098dc6e1"
+			"Comment": "mynewt_0_9_0_tag-454-gd3462c4",
+			"Rev": "d3462c4a6b00592a47e39b0bee3935e94a287038"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/xact",
-			"Comment": "mynewt_0_9_0_tag-448-ga808bde",
-			"Rev": "a808bde2b242416e3ad2e52d125fa26f098dc6e1"
+			"Comment": "mynewt_0_9_0_tag-454-gd3462c4",
+			"Rev": "d3462c4a6b00592a47e39b0bee3935e94a287038"
 		},
 		{
 			"ImportPath": "mynewt.apache.org/newtmgr/nmxact/xport",
-			"Comment": "mynewt_0_9_0_tag-448-ga808bde",
-			"Rev": "a808bde2b242416e3ad2e52d125fa26f098dc6e1"
+			"Comment": "mynewt_0_9_0_tag-454-gd3462c4",
+			"Rev": "d3462c4a6b00592a47e39b0bee3935e94a287038"
 		}
 	]
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newt/util/unixchild/unixchild.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newt/util/unixchild/unixchild.go b/newtmgr/vendor/mynewt.apache.org/newt/util/unixchild/unixchild.go
index b8be35d..91930c0 100644
--- a/newtmgr/vendor/mynewt.apache.org/newt/util/unixchild/unixchild.go
+++ b/newtmgr/vendor/mynewt.apache.org/newt/util/unixchild/unixchild.go
@@ -60,14 +60,12 @@ type Config struct {
 	Depth         int
 	MaxMsgSz      int
 	AcceptTimeout time.Duration
-	Restart       bool
 }
 
 type clientState uint32
 
 const (
 	CLIENT_STATE_STOPPED clientState = iota
-	CLIENT_STATE_STARTING
 	CLIENT_STATE_STARTED
 	CLIENT_STATE_STOPPING
 )
@@ -81,11 +79,9 @@ type Client struct {
 	childArgs     []string
 	maxMsgSz      int
 	acceptTimeout time.Duration
-	restart       bool
 	stop          chan bool
 	stopped       chan bool
 	state         clientState
-	stateMutex    sync.Mutex
 }
 
 func New(conf Config) *Client {
@@ -98,7 +94,6 @@ func New(conf Config) *Client {
 		ToChild:       make(chan []byte, conf.Depth),
 		ErrChild:      make(chan error),
 		acceptTimeout: conf.AcceptTimeout,
-		restart:       conf.Restart,
 		stop:          make(chan bool),
 		stopped:       make(chan bool),
 	}
@@ -110,42 +105,6 @@ func New(conf Config) *Client {
 	return c
 }
 
-func (c *Client) getState() clientState {
-	c.stateMutex.Lock()
-	defer c.stateMutex.Unlock()
-
-	return c.state
-}
-
-func (c *Client) setState(toState clientState) {
-	c.stateMutex.Lock()
-	defer c.stateMutex.Unlock()
-
-	c.state = toState
-}
-
-func (c *Client) setStateIf(toState clientState,
-	pred func(st clientState) bool) (bool, clientState) {
-
-	c.stateMutex.Lock()
-	defer c.stateMutex.Unlock()
-
-	if pred(c.state) {
-		c.state = toState
-		return true, toState
-	}
-
-	return false, c.state
-
-}
-
-func (c *Client) setStateFrom(fromState clientState,
-	toState clientState) (bool, clientState) {
-
-	return c.setStateIf(toState,
-		func(st clientState) bool { return st == fromState })
-}
-
 func (c *Client) startChild() (*exec.Cmd, error) {
 	subProcess := exec.Command(c.childPath, c.childArgs...)
 
@@ -249,20 +208,19 @@ func (c *Client) handleChild(con net.Conn) {
 }
 
 func (c *Client) Stop() {
-	ok, _ := c.setStateIf(CLIENT_STATE_STOPPING,
-		func(st clientState) bool {
-			return st != CLIENT_STATE_STOPPING
-		})
-	if !ok {
+	if c.state != CLIENT_STATE_STARTED {
 		return
 	}
 
+	c.state = CLIENT_STATE_STOPPING
 	log.Debugf("Stopping client")
 
 	c.stop <- true
 
 	select {
 	case <-c.stopped:
+		c.deleteSocket()
+		c.state = CLIENT_STATE_STOPPED
 		log.Debugf("Stopped client")
 		return
 	}
@@ -277,63 +235,57 @@ func (c *Client) acceptDeadline() *time.Time {
 	return &t
 }
 
+func (c *Client) deleteSocket() {
+	log.Debugf("deleting socket")
+	os.Remove(c.sockPath)
+}
+
 func (c *Client) Start() error {
-	ok, state := c.setStateFrom(CLIENT_STATE_STOPPED, CLIENT_STATE_STARTING)
-	if !ok {
-		return fmt.Errorf("client in invalid state for stating: %d", state)
+	if c.state != CLIENT_STATE_STOPPED {
+		return fmt.Errorf("Attempt to start unixchild twice")
 	}
 
 	l, err := net.Listen("unix", c.sockPath)
 	if err != nil {
-		c.setState(CLIENT_STATE_STOPPED)
+		c.deleteSocket()
+		return err
+	}
+
+	cmd, err := c.startChild()
+	if err != nil {
+		err = fmt.Errorf("unixchild start error: %s", err.Error())
+		log.Debugf("%s", err.Error())
+		c.deleteSocket()
+		return err
+	}
+
+	if t := c.acceptDeadline(); t != nil {
+		l.(*net.UnixListener).SetDeadline(*t)
+	}
+	fd, err := l.Accept()
+	if err != nil {
+		err = NewUcAcceptError(fmt.Sprintf("unixchild accept error: %s",
+			err.Error()))
+		c.deleteSocket()
 		return err
 	}
 
-	var cmd *exec.Cmd
+	c.state = CLIENT_STATE_STARTED
 
 	go func() {
-		for {
-			var err error
-			cmd, err = c.startChild()
-			if err != nil {
-				log.Debugf("unixchild start error: %s", err.Error())
-				c.ErrChild <- fmt.Errorf("Child start error: %s", err.Error())
-			} else {
-				if t := c.acceptDeadline(); t != nil {
-					l.(*net.UnixListener).SetDeadline(*t)
-				}
-				fd, err := l.Accept()
-				if err != nil {
-					text := fmt.Sprintf("unixchild accept error: %s",
-						err.Error())
-					c.ErrChild <- NewUcAcceptError(text)
-				} else {
-					c.setState(CLIENT_STATE_STARTED)
-					c.handleChild(fd)
-					c.ErrChild <- fmt.Errorf("Child exited")
-				}
-			}
-			if c.getState() == CLIENT_STATE_STOPPING {
-				log.Debugf("unixchild exit loop")
-				return
-			}
-			time.Sleep(time.Second)
-		}
+		c.handleChild(fd)
+		c.Stop()
+		c.ErrChild <- fmt.Errorf("child process terminated")
 	}()
 
 	go func() {
-		select {
-		case <-c.stop:
-			if c.getState() == CLIENT_STATE_STARTED {
-				l.Close()
-			}
-			if cmd != nil {
-				cmd.Process.Kill()
-			}
-			log.Debugf("deleting socket")
-			os.Remove(c.sockPath)
-			c.stopped <- true
+		<-c.stop
+		l.Close()
+		if cmd != nil {
+			cmd.Process.Kill()
 		}
+		c.deleteSocket()
+		c.stopped <- true
 	}()
 
 	return nil

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_act.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_act.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_act.go
index 2aa6678..cb6cb00 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_act.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_act.go
@@ -56,7 +56,7 @@ func terminate(x *BleXport, bl *BleListener, r *BleTerminateReq) error {
 			default:
 			}
 
-		case <-bl.AfterTimeout(x.rspTimeout):
+		case <-bl.AfterTimeout(x.RspTimeout()):
 			return BhdTimeoutError(MSG_TYPE_TERMINATE)
 		}
 	}
@@ -92,7 +92,7 @@ func connCancel(x *BleXport, bl *BleListener, r *BleConnCancelReq) error {
 			default:
 			}
 
-		case <-bl.AfterTimeout(x.rspTimeout):
+		case <-bl.AfterTimeout(x.RspTimeout()):
 			return BhdTimeoutError(MSG_TYPE_TERMINATE)
 		}
 	}
@@ -148,7 +148,7 @@ func discSvcUuid(x *BleXport, bl *BleListener, r *BleDiscSvcUuidReq) (
 			default:
 			}
 
-		case <-bl.AfterTimeout(x.rspTimeout):
+		case <-bl.AfterTimeout(x.RspTimeout()):
 			return nil, BhdTimeoutError(MSG_TYPE_DISC_SVC_UUID)
 		}
 	}
@@ -198,7 +198,7 @@ func discAllChrs(x *BleXport, bl *BleListener, r *BleDiscAllChrsReq) (
 			default:
 			}
 
-		case <-bl.AfterTimeout(x.rspTimeout):
+		case <-bl.AfterTimeout(x.RspTimeout()):
 			return nil, BhdTimeoutError(MSG_TYPE_DISC_ALL_CHRS)
 		}
 	}
@@ -235,7 +235,7 @@ func writeCmd(x *BleXport, bl *BleListener, r *BleWriteCmdReq) error {
 			default:
 			}
 
-		case <-bl.AfterTimeout(x.rspTimeout):
+		case <-bl.AfterTimeout(x.RspTimeout()):
 			return BhdTimeoutError(MSG_TYPE_WRITE_CMD)
 		}
 	}
@@ -281,7 +281,7 @@ func exchangeMtu(x *BleXport, bl *BleListener, r *BleExchangeMtuReq) (
 			default:
 			}
 
-		case <-bl.AfterTimeout(x.rspTimeout):
+		case <-bl.AfterTimeout(x.RspTimeout()):
 			return 0, BhdTimeoutError(MSG_TYPE_EXCHANGE_MTU)
 		}
 	}
@@ -320,7 +320,7 @@ func scan(x *BleXport, bl *BleListener, r *BleScanReq,
 			default:
 			}
 
-		case <-bl.AfterTimeout(x.rspTimeout):
+		case <-bl.AfterTimeout(x.RspTimeout()):
 			return BhdTimeoutError(MSG_TYPE_EXCHANGE_MTU)
 
 		case <-abortChan:
@@ -356,7 +356,7 @@ func scanCancel(x *BleXport, bl *BleListener, r *BleScanCancelReq) error {
 			default:
 			}
 
-		case <-bl.AfterTimeout(x.rspTimeout):
+		case <-bl.AfterTimeout(x.RspTimeout()):
 			return BhdTimeoutError(MSG_TYPE_EXCHANGE_MTU)
 		}
 	}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_fsm.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_fsm.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_fsm.go
index cf12bdc..39bfdfc 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_fsm.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_fsm.go
@@ -216,6 +216,30 @@ func (bf *BleFsm) calcDisconnectType() BleFsmDisconnectType {
 	}
 }
 
+func (bf *BleFsm) onDisconnect(err error) {
+	log.Debugf(err.Error())
+
+	bf.mtx.Lock()
+	bls := make([]*BleListener, 0, len(bf.bls))
+	for bl, _ := range bf.bls {
+		bls = append(bls, bl)
+	}
+	bf.mtx.Unlock()
+
+	// Remember some fields before we clear them.
+	dt := bf.calcDisconnectType()
+	peer := *bf.peerDev
+
+	bf.setState(SESN_STATE_UNCONNECTED)
+	bf.peerDev = nil
+
+	for _, bl := range bls {
+		bl.ErrChan <- err
+	}
+
+	bf.params.DisconnectCb(dt, peer, err)
+}
+
 func (bf *BleFsm) connectListen(seq int) error {
 	bf.connChan = make(chan error, 1)
 
@@ -228,7 +252,10 @@ func (bf *BleFsm) connectListen(seq int) error {
 		defer bf.removeBleSeqListener(seq)
 		for {
 			select {
-			case <-bl.ErrChan:
+			case err := <-bl.ErrChan:
+				// Transport reported error.  Assume all connections have
+				// dropped.
+				bf.onDisconnect(err)
 				return
 
 			case bm := <-bl.BleChan:
@@ -281,33 +308,13 @@ func (bf *BleFsm) connectListen(seq int) error {
 
 				case *BleDisconnectEvt:
 					err := bf.disconnectError(msg.Reason)
-					log.Debugf(err.Error())
-
-					bf.mtx.Lock()
-					bls := make([]*BleListener, 0, len(bf.bls))
-					for bl, _ := range bf.bls {
-						bls = append(bls, bl)
-					}
-					bf.mtx.Unlock()
-
-					// Remember some fields before we clear them.
-					dt := bf.calcDisconnectType()
-					peer := *bf.peerDev
-
-					bf.setState(SESN_STATE_UNCONNECTED)
-					bf.peerDev = nil
-
-					for _, bl := range bls {
-						bl.ErrChan <- err
-					}
-
-					bf.params.DisconnectCb(dt, peer, err)
+					bf.onDisconnect(err)
 					return
 
 				default:
 				}
 
-			case <-bl.AfterTimeout(bf.params.Bx.rspTimeout):
+			case <-bl.AfterTimeout(bf.params.Bx.RspTimeout()):
 				bf.connChan <- BhdTimeoutError(MSG_TYPE_CONNECT)
 			}
 		}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_oic_sesn.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_oic_sesn.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_oic_sesn.go
index 4001960..5fa9291 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_oic_sesn.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_oic_sesn.go
@@ -5,6 +5,8 @@ import (
 	"sync"
 	"time"
 
+	log "github.com/Sirupsen/logrus"
+
 	"mynewt.apache.org/newt/util"
 	. "mynewt.apache.org/newtmgr/nmxact/bledefs"
 	"mynewt.apache.org/newtmgr/nmxact/nmp"
@@ -135,11 +137,21 @@ func (bos *BleOicSesn) AbortRx(seq uint8) error {
 func (bos *BleOicSesn) Open() error {
 	var err error
 	for i := 0; i < bos.connTries; i++ {
+		log.Debugf("Opening BLE session; try %d/%d", i+1, bos.connTries)
+
 		var retry bool
 		retry, err = bos.bf.Start()
 		if !retry {
 			break
 		}
+
+		if bos.blockUntilClosed(1*time.Second) != nil {
+			// Just close the session manually and report the original error.
+			bos.Close()
+			return err
+		}
+
+		log.Debugf("Connection to BLE peer dropped immediately; retrying")
 	}
 
 	return err

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_plain_sesn.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_plain_sesn.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_plain_sesn.go
index 012a301..15419a9 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_plain_sesn.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_plain_sesn.go
@@ -5,6 +5,8 @@ import (
 	"sync"
 	"time"
 
+	log "github.com/Sirupsen/logrus"
+
 	"mynewt.apache.org/newt/util"
 	. "mynewt.apache.org/newtmgr/nmxact/bledefs"
 	"mynewt.apache.org/newtmgr/nmxact/nmp"
@@ -128,6 +130,8 @@ func (bps *BlePlainSesn) AbortRx(seq uint8) error {
 func (bps *BlePlainSesn) Open() error {
 	var err error
 	for i := 0; i < bps.connTries; i++ {
+		log.Debugf("Opening BLE session; try %d/%d", i+1, bps.connTries)
+
 		var retry bool
 		retry, err = bps.bf.Start()
 		if !retry {
@@ -139,6 +143,8 @@ func (bps *BlePlainSesn) Open() error {
 			bps.Close()
 			return err
 		}
+
+		log.Debugf("Connection to BLE peer dropped immediately; retrying")
 	}
 
 	return err

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_xport.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_xport.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_xport.go
index ba38b9d..32ced04 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_xport.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/ble_xport.go
@@ -9,9 +9,9 @@ import (
 
 	log "github.com/Sirupsen/logrus"
 
+	"mynewt.apache.org/newt/util/unixchild"
 	"mynewt.apache.org/newtmgr/nmxact/nmxutil"
 	"mynewt.apache.org/newtmgr/nmxact/sesn"
-	"mynewt.apache.org/newt/util/unixchild"
 )
 
 type XportCfg struct {
@@ -33,13 +33,17 @@ type XportCfg struct {
 
 	// Path of the BLE controller device (e.g., /dev/ttyUSB0).
 	DevPath string
+
+	// How long to allow for the host and controller to sync at startup.
+	SyncTimeout time.Duration
 }
 
 func NewXportCfg() XportCfg {
 	return XportCfg{
 		BlehostdAcceptTimeout: time.Second,
-		BlehostdRestart:       true,
 		BlehostdRspTimeout:    time.Second,
+		BlehostdRestart:       true,
+		SyncTimeout:           10 * time.Second,
 	}
 }
 
@@ -49,39 +53,42 @@ const (
 	BLE_XPORT_STATE_STOPPED BleXportState = iota
 	BLE_XPORT_STATE_STARTING
 	BLE_XPORT_STATE_STARTED
+	BLE_XPORT_STATE_STOPPING
 )
 
 // Implements xport.Xport.
 type BleXport struct {
-	Bd     *BleDispatcher
-	client *unixchild.Client
-	state  BleXportState
-
-	syncTimeout time.Duration
-	rspTimeout  time.Duration
+	Bd               *BleDispatcher
+	client           *unixchild.Client
+	state            BleXportState
+	stopChan         chan struct{}
+	shutdownChan     chan bool
+	numStopListeners int
+
+	cfg XportCfg
 }
 
 func NewBleXport(cfg XportCfg) (*BleXport, error) {
-	config := unixchild.Config{
-		SockPath:      cfg.SockPath,
-		ChildPath:     cfg.BlehostdPath,
-		ChildArgs:     []string{cfg.DevPath, cfg.SockPath},
-		Depth:         10,
-		MaxMsgSz:      10240,
-		AcceptTimeout: cfg.BlehostdAcceptTimeout,
-		Restart:       cfg.BlehostdRestart,
+	bx := &BleXport{
+		Bd:           NewBleDispatcher(),
+		shutdownChan: make(chan bool),
+		cfg:          cfg,
 	}
 
-	c := unixchild.New(config)
+	return bx, nil
+}
 
-	bx := &BleXport{
-		client:      c,
-		Bd:          NewBleDispatcher(),
-		syncTimeout: 10 * time.Second,
-		rspTimeout:  cfg.BlehostdRspTimeout,
+func (bx *BleXport) createUnixChild() {
+	config := unixchild.Config{
+		SockPath:      bx.cfg.SockPath,
+		ChildPath:     bx.cfg.BlehostdPath,
+		ChildArgs:     []string{bx.cfg.DevPath, bx.cfg.SockPath},
+		Depth:         10,
+		MaxMsgSz:      10240,
+		AcceptTimeout: bx.cfg.BlehostdAcceptTimeout,
 	}
 
-	return bx, nil
+	bx.client = unixchild.New(config)
 }
 
 func (bx *BleXport) BuildSesn(cfg sesn.SesnCfg) (sesn.Sesn, error) {
@@ -175,18 +182,46 @@ func (bx *BleXport) initialSyncCheck() (bool, *BleListener, error) {
 	return synced, bl, nil
 }
 
-func (bx *BleXport) onError(err error) {
-	if !bx.setStateFrom(BLE_XPORT_STATE_STARTED, BLE_XPORT_STATE_STOPPED) &&
-		!bx.setStateFrom(BLE_XPORT_STATE_STARTING, BLE_XPORT_STATE_STOPPED) {
+func (bx *BleXport) shutdown(restart bool, err error) {
+	var fullyStarted bool
+
+	if bx.setStateFrom(BLE_XPORT_STATE_STARTED,
+		BLE_XPORT_STATE_STOPPING) {
 
+		fullyStarted = true
+	} else if bx.setStateFrom(BLE_XPORT_STATE_STARTING,
+		BLE_XPORT_STATE_STOPPING) {
+
+		fullyStarted = false
+	} else {
 		// Stop already in progress.
 		return
 	}
-	bx.Bd.ErrorAll(err)
+
+	// Stop the unixchild instance (blehostd + socket).
 	if bx.client != nil {
 		bx.client.Stop()
+
+		// Unblock the unixchild instance.
 		bx.client.FromChild <- nil
 	}
+
+	// Indicate an error to all of this transport's listeners.  This prevents
+	// them from blocking endlessly while awaiting a BLE message.
+	bx.Bd.ErrorAll(err)
+
+	// Stop all of this transport's go routines.
+	for i := 0; i < bx.numStopListeners; i++ {
+		bx.stopChan <- struct{}{}
+	}
+
+	bx.setStateFrom(BLE_XPORT_STATE_STOPPING, BLE_XPORT_STATE_STOPPED)
+
+	// Indicate that the shutdown is complete.  If restarts are enabled on this
+	// transport, this signals that the transport should be started again.
+	if fullyStarted {
+		bx.shutdownChan <- restart
+	}
 }
 
 func (bx *BleXport) setStateFrom(from BleXportState, to BleXportState) bool {
@@ -200,42 +235,68 @@ func (bx *BleXport) getState() BleXportState {
 }
 
 func (bx *BleXport) Stop() error {
-	bx.onError(nil)
+	bx.shutdown(false, nil)
 	return nil
 }
 
-func (bx *BleXport) Start() error {
+func (bx *BleXport) startOnce() error {
 	if !bx.setStateFrom(BLE_XPORT_STATE_STOPPED, BLE_XPORT_STATE_STARTING) {
 		return nmxutil.NewXportError("BLE xport started twice")
 	}
 
+	bx.stopChan = make(chan struct{})
+	bx.numStopListeners = 0
+	bx.Bd.Clear()
+
+	bx.createUnixChild()
 	if err := bx.client.Start(); err != nil {
-		return nmxutil.NewXportError(
-			"Failed to start child child process: " + err.Error())
+		if unixchild.IsUcAcceptError(err) {
+			err = nmxutil.NewXportError(
+				"blehostd did not connect to socket; " +
+					"controller not attached?")
+		} else {
+			panic(err.Error())
+			err = nmxutil.NewXportError(
+				"Failed to start child process: " + err.Error())
+		}
+		bx.shutdown(true, err)
+		return err
 	}
 
 	go func() {
-		err := <-bx.client.ErrChild
-		if unixchild.IsUcAcceptError(err) {
-			err = fmt.Errorf("blehostd did not connect to socket; " +
-				"controller not attached?")
+		bx.numStopListeners++
+		for {
+			select {
+			case err := <-bx.client.ErrChild:
+				err = nmxutil.NewXportError("BLE transport error: " +
+					err.Error())
+				go bx.shutdown(true, err)
+
+			case <-bx.stopChan:
+				return
+			}
 		}
-		bx.onError(err)
-		return
 	}()
 
 	go func() {
+		bx.numStopListeners++
 		for {
-			if _, err := bx.rx(); err != nil {
-				// The error should have been reported to everyone interested.
-				break
+			select {
+			case buf := <-bx.client.FromChild:
+				if len(buf) != 0 {
+					log.Debugf("Receive from blehostd:\n%s", hex.Dump(buf))
+					bx.Bd.Dispatch(buf)
+				}
+
+			case <-bx.stopChan:
+				return
 			}
 		}
 	}()
 
 	synced, bl, err := bx.initialSyncCheck()
 	if err != nil {
-		bx.Stop()
+		bx.shutdown(true, err)
 		return err
 	}
 
@@ -246,6 +307,7 @@ func (bx *BleXport) Start() error {
 		for {
 			select {
 			case err := <-bl.ErrChan:
+				bx.shutdown(true, err)
 				return err
 			case bm := <-bl.BleChan:
 				switch msg := bm.(type) {
@@ -254,35 +316,38 @@ func (bx *BleXport) Start() error {
 						break SyncLoop
 					}
 				}
-			case <-time.After(bx.syncTimeout):
-				bx.Stop()
-				return nmxutil.NewXportError(
+			case <-time.After(bx.cfg.SyncTimeout):
+				err := nmxutil.NewXportError(
 					"Timeout waiting for host <-> controller sync")
+				bx.shutdown(true, err)
+				return err
 			}
 		}
 	}
 
 	// Host and controller are synced.  Listen for sync loss in the background.
 	go func() {
+		bx.numStopListeners++
 		for {
 			select {
 			case err := <-bl.ErrChan:
-				bx.onError(err)
-				return
+				go bx.shutdown(true, err)
 			case bm := <-bl.BleChan:
 				switch msg := bm.(type) {
 				case *BleSyncEvt:
 					if !msg.Synced {
-						bx.onError(nmxutil.NewXportError(
+						go bx.shutdown(true, nmxutil.NewXportError(
 							"BLE host <-> controller sync lost"))
-						return
 					}
 				}
+			case <-bx.stopChan:
+				return
 			}
 		}
 	}()
 
 	if !bx.setStateFrom(BLE_XPORT_STATE_STARTING, BLE_XPORT_STATE_STARTED) {
+		bx.shutdown(true, err)
 		return nmxutil.NewXportError(
 			"Internal error; BLE transport in unexpected state")
 	}
@@ -290,6 +355,47 @@ func (bx *BleXport) Start() error {
 	return nil
 }
 
+func (bx *BleXport) Start() error {
+	// Try to start the transport.  If this first attempt fails, report the
+	// error and don't retry.
+	if err := bx.startOnce(); err != nil {
+		log.Debugf("Error starting BLE transport: %s",
+			err.Error())
+		return err
+	}
+
+	// Now that the first start attempt has succeeded, start a restart loop in
+	// the background.
+	go func() {
+		// Block until transport shuts down.
+		restart := <-bx.shutdownChan
+		for {
+			// If restarts are disabled, or if the shutdown was a result of an
+			// explicit stop call (instead of an unexpected error), stop
+			// restarting the transport.
+			if !bx.cfg.BlehostdRestart || !restart {
+				break
+			}
+
+			// Wait a second before the next restart.  This is necessary to
+			// ensure the unix domain socket can be rebound.
+			time.Sleep(time.Second)
+
+			// Attempt to start the transport again.
+			if err := bx.startOnce(); err != nil {
+				// Start attempt failed.
+				log.Debugf("Error starting BLE transport: %s",
+					err.Error())
+			} else {
+				// Success.  Block until the transport shuts down.
+				restart = <-bx.shutdownChan
+			}
+		}
+	}()
+
+	return nil
+}
+
 func (bx *BleXport) txNoSync(data []byte) {
 	log.Debugf("Tx to blehostd:\n%s", hex.Dump(data))
 	bx.client.ToChild <- data
@@ -297,23 +403,15 @@ func (bx *BleXport) txNoSync(data []byte) {
 
 func (bx *BleXport) Tx(data []byte) error {
 	if bx.getState() != BLE_XPORT_STATE_STARTED {
-		return nmxutil.NewXportError("Attempt to transmit before BLE xport " +
-			"fully started")
+		return nmxutil.NewXportError(
+			fmt.Sprintf("Attempt to transmit before BLE xport fully started; "+
+				"state=%d", bx.getState()))
 	}
 
 	bx.txNoSync(data)
 	return nil
 }
 
-func (bx *BleXport) rx() ([]byte, error) {
-	select {
-	case err := <-bx.client.ErrChild:
-		return nil, err
-	case buf := <-bx.client.FromChild:
-		if len(buf) != 0 {
-			log.Debugf("Receive from blehostd:\n%s", hex.Dump(buf))
-			bx.Bd.Dispatch(buf)
-		}
-		return buf, nil
-	}
+func (bx *BleXport) RspTimeout() time.Duration {
+	return bx.cfg.BlehostdRspTimeout
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/dispatch.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/dispatch.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/dispatch.go
index 546fc11..c9ef39e 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/dispatch.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmble/dispatch.go
@@ -267,7 +267,10 @@ func (bd *BleDispatcher) Dispatch(data []byte) {
 		return
 	}
 
+	bd.mutex.Lock()
 	_, listener := bd.findListener(base)
+	bd.mutex.Unlock()
+
 	if listener == nil {
 		log.Debugf(
 			"No BLE listener for op=%d type=%d seq=%d connHandle=%d",
@@ -295,3 +298,15 @@ func (bd *BleDispatcher) ErrorAll(err error) {
 		listener.ErrChan <- err
 	}
 }
+
+func (bd *BleDispatcher) Clear() {
+	bd.mutex.Lock()
+	defer bd.mutex.Unlock()
+
+	for s, _ := range bd.seqMap {
+		delete(bd.seqMap, s)
+	}
+	for b, _ := range bd.baseMap {
+		delete(bd.baseMap, b)
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmp/dispatch.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmp/dispatch.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmp/dispatch.go
index 7b1ad11..5b39a9b 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmp/dispatch.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/nmp/dispatch.go
@@ -39,6 +39,7 @@ func NewNmpListener() *NmpListener {
 	return &NmpListener{
 		RspChan: make(chan NmpRsp, 1),
 		ErrChan: make(chan error, 1),
+		tmoChan: make(chan time.Time, 1),
 	}
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/sesn/sesn.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/sesn/sesn.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/sesn/sesn.go
index 8ef8934..0782e63 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/sesn/sesn.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/sesn/sesn.go
@@ -12,6 +12,13 @@ type TxOptions struct {
 	Tries   int
 }
 
+func NewTxOptions() TxOptions {
+	return TxOptions{
+		Timeout: 10 * time.Second,
+		Tries:   1,
+	}
+}
+
 func (opt *TxOptions) AfterTimeout() <-chan time.Time {
 	if opt.Timeout == 0 {
 		return nil

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/cmd.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/cmd.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/cmd.go
index d5d7a23..9bc3728 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/cmd.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/cmd.go
@@ -45,6 +45,12 @@ type CmdBase struct {
 	abortErr  error
 }
 
+func NewCmdBase() CmdBase {
+	return CmdBase{
+		txOptions: sesn.NewTxOptions(),
+	}
+}
+
 func (c *CmdBase) TxOptions() sesn.TxOptions {
 	return c.txOptions
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/config.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/config.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/config.go
index ddc893b..fc55505 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/config.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/config.go
@@ -15,7 +15,9 @@ type ConfigReadCmd struct {
 }
 
 func NewConfigReadCmd() *ConfigReadCmd {
-	return &ConfigReadCmd{}
+	return &ConfigReadCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type ConfigReadResult struct {
@@ -56,7 +58,9 @@ type ConfigWriteCmd struct {
 }
 
 func NewConfigWriteCmd() *ConfigWriteCmd {
-	return &ConfigWriteCmd{}
+	return &ConfigWriteCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type ConfigWriteResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/crash.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/crash.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/crash.go
index ebb94c7..f665c88 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/crash.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/crash.go
@@ -56,7 +56,9 @@ type CrashCmd struct {
 }
 
 func NewCrashCmd() *CrashCmd {
-	return &CrashCmd{}
+	return &CrashCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type CrashResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/datetime.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/datetime.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/datetime.go
index 27bd089..f6622df 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/datetime.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/datetime.go
@@ -14,7 +14,9 @@ type DateTimeReadCmd struct {
 }
 
 func NewDateTimeReadCmd() *DateTimeReadCmd {
-	return &DateTimeReadCmd{}
+	return &DateTimeReadCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type DateTimeReadResult struct {
@@ -53,7 +55,9 @@ type DateTimeWriteCmd struct {
 }
 
 func NewDateTimeWriteCmd() *DateTimeWriteCmd {
-	return &DateTimeWriteCmd{}
+	return &DateTimeWriteCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type DateTimeWriteResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/echo.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/echo.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/echo.go
index 09622b2..630e876 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/echo.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/echo.go
@@ -11,7 +11,9 @@ type EchoCmd struct {
 }
 
 func NewEchoCmd() *EchoCmd {
-	return &EchoCmd{}
+	return &EchoCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type EchoResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/fs.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/fs.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/fs.go
index 0fe32c6..c6668de 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/fs.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/fs.go
@@ -19,7 +19,9 @@ type FsDownloadCmd struct {
 }
 
 func NewFsDownloadCmd() *FsDownloadCmd {
-	return &FsDownloadCmd{}
+	return &FsDownloadCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type FsDownloadResult struct {
@@ -81,7 +83,9 @@ type FsUploadCmd struct {
 }
 
 func NewFsUploadCmd() *FsUploadCmd {
-	return &FsUploadCmd{}
+	return &FsUploadCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type FsUploadResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/image.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/image.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/image.go
index 615dd74..55ba44c 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/image.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/image.go
@@ -23,7 +23,9 @@ type ImageUploadResult struct {
 }
 
 func NewImageUploadCmd() *ImageUploadCmd {
-	return &ImageUploadCmd{}
+	return &ImageUploadCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 func newImageUploadResult() *ImageUploadResult {
@@ -127,7 +129,9 @@ type ImageStateReadResult struct {
 }
 
 func NewImageStateReadCmd() *ImageStateReadCmd {
-	return &ImageStateReadCmd{}
+	return &ImageStateReadCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 func newImageStateReadResult() *ImageStateReadResult {
@@ -167,7 +171,9 @@ type ImageStateWriteResult struct {
 }
 
 func NewImageStateWriteCmd() *ImageStateWriteCmd {
-	return &ImageStateWriteCmd{}
+	return &ImageStateWriteCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 func newImageStateWriteResult() *ImageStateWriteResult {
@@ -207,7 +213,9 @@ type CoreListResult struct {
 }
 
 func NewCoreListCmd() *CoreListCmd {
-	return &CoreListCmd{}
+	return &CoreListCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 func newCoreListResult() *CoreListResult {
@@ -247,7 +255,9 @@ type CoreLoadResult struct {
 }
 
 func NewCoreLoadCmd() *CoreLoadCmd {
-	return &CoreLoadCmd{}
+	return &CoreLoadCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 func newCoreLoadResult() *CoreLoadResult {
@@ -306,7 +316,9 @@ type CoreEraseResult struct {
 }
 
 func NewCoreEraseCmd() *CoreEraseCmd {
-	return &CoreEraseCmd{}
+	return &CoreEraseCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 func newCoreEraseResult() *CoreEraseResult {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/log.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/log.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/log.go
index 86b348f..f71f8a3 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/log.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/log.go
@@ -17,7 +17,9 @@ type LogShowCmd struct {
 }
 
 func NewLogShowCmd() *LogShowCmd {
-	return &LogShowCmd{}
+	return &LogShowCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type LogShowResult struct {
@@ -58,7 +60,9 @@ type LogListCmd struct {
 }
 
 func NewLogListCmd() *LogListCmd {
-	return &LogListCmd{}
+	return &LogListCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type LogListResult struct {
@@ -96,7 +100,9 @@ type LogModuleListCmd struct {
 }
 
 func NewLogModuleListCmd() *LogModuleListCmd {
-	return &LogModuleListCmd{}
+	return &LogModuleListCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type LogModuleListResult struct {
@@ -134,7 +140,9 @@ type LogLevelListCmd struct {
 }
 
 func NewLogLevelListCmd() *LogLevelListCmd {
-	return &LogLevelListCmd{}
+	return &LogLevelListCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type LogLevelListResult struct {
@@ -172,7 +180,9 @@ type LogClearCmd struct {
 }
 
 func NewLogClearCmd() *LogClearCmd {
-	return &LogClearCmd{}
+	return &LogClearCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type LogClearResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/mpstat.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/mpstat.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/mpstat.go
index acff3e2..cb7b0da 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/mpstat.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/mpstat.go
@@ -10,7 +10,9 @@ type MempoolStatCmd struct {
 }
 
 func NewMempoolStatCmd() *MempoolStatCmd {
-	return &MempoolStatCmd{}
+	return &MempoolStatCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type MempoolStatResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/reset.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/reset.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/reset.go
index 397ad60..08a1040 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/reset.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/reset.go
@@ -11,7 +11,9 @@ type ResetCmd struct {
 }
 
 func NewResetCmd() *ResetCmd {
-	return &ResetCmd{}
+	return &ResetCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type ResetResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/run.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/run.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/run.go
index 28d71a9..d1af353 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/run.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/run.go
@@ -16,7 +16,9 @@ type RunTestCmd struct {
 }
 
 func NewRunTestCmd() *RunTestCmd {
-	return &RunTestCmd{}
+	return &RunTestCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type RunTestResult struct {
@@ -56,7 +58,9 @@ type RunListCmd struct {
 }
 
 func NewRunListCmd() *RunListCmd {
-	return &RunListCmd{}
+	return &RunListCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type RunListResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/stat.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/stat.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/stat.go
index a38eba9..f921afa 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/stat.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/stat.go
@@ -15,7 +15,9 @@ type StatReadCmd struct {
 }
 
 func NewStatReadCmd() *StatReadCmd {
-	return &StatReadCmd{}
+	return &StatReadCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type StatReadResult struct {
@@ -54,7 +56,9 @@ type StatListCmd struct {
 }
 
 func NewStatListCmd() *StatListCmd {
-	return &StatListCmd{}
+	return &StatListCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type StatListResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/7f57aa2d/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/taskstat.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/taskstat.go b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/taskstat.go
index bb03357..a2e82c4 100644
--- a/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/taskstat.go
+++ b/newtmgr/vendor/mynewt.apache.org/newtmgr/nmxact/xact/taskstat.go
@@ -10,7 +10,9 @@ type TaskStatCmd struct {
 }
 
 func NewTaskStatCmd() *TaskStatCmd {
-	return &TaskStatCmd{}
+	return &TaskStatCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type TaskStatResult struct {



[2/6] incubator-mynewt-newtmgr git commit: nmxact - Stability when xport fails

Posted by cc...@apache.org.
nmxact - Stability when xport fails


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/commit/db639f93
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/tree/db639f93
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/diff/db639f93

Branch: refs/heads/master
Commit: db639f9313a27c051c0b6dd9e13840549f3f5acd
Parents: 0384fcf
Author: Christopher Collins <cc...@apache.org>
Authored: Fri Mar 31 18:26:35 2017 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Mon Apr 3 16:49:25 2017 -0700

----------------------------------------------------------------------
 nmxact/nmble/ble_act.go        | 16 +++----
 nmxact/nmble/ble_fsm.go        | 53 +++++++++++++----------
 nmxact/nmble/ble_oic_sesn.go   | 12 ++++++
 nmxact/nmble/ble_plain_sesn.go |  6 +++
 nmxact/nmble/ble_xport.go      | 85 ++++++++++++++++++++-----------------
 nmxact/nmp/dispatch.go         |  1 +
 6 files changed, 103 insertions(+), 70 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/db639f93/nmxact/nmble/ble_act.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_act.go b/nmxact/nmble/ble_act.go
index 2aa6678..cb6cb00 100644
--- a/nmxact/nmble/ble_act.go
+++ b/nmxact/nmble/ble_act.go
@@ -56,7 +56,7 @@ func terminate(x *BleXport, bl *BleListener, r *BleTerminateReq) error {
 			default:
 			}
 
-		case <-bl.AfterTimeout(x.rspTimeout):
+		case <-bl.AfterTimeout(x.RspTimeout()):
 			return BhdTimeoutError(MSG_TYPE_TERMINATE)
 		}
 	}
@@ -92,7 +92,7 @@ func connCancel(x *BleXport, bl *BleListener, r *BleConnCancelReq) error {
 			default:
 			}
 
-		case <-bl.AfterTimeout(x.rspTimeout):
+		case <-bl.AfterTimeout(x.RspTimeout()):
 			return BhdTimeoutError(MSG_TYPE_TERMINATE)
 		}
 	}
@@ -148,7 +148,7 @@ func discSvcUuid(x *BleXport, bl *BleListener, r *BleDiscSvcUuidReq) (
 			default:
 			}
 
-		case <-bl.AfterTimeout(x.rspTimeout):
+		case <-bl.AfterTimeout(x.RspTimeout()):
 			return nil, BhdTimeoutError(MSG_TYPE_DISC_SVC_UUID)
 		}
 	}
@@ -198,7 +198,7 @@ func discAllChrs(x *BleXport, bl *BleListener, r *BleDiscAllChrsReq) (
 			default:
 			}
 
-		case <-bl.AfterTimeout(x.rspTimeout):
+		case <-bl.AfterTimeout(x.RspTimeout()):
 			return nil, BhdTimeoutError(MSG_TYPE_DISC_ALL_CHRS)
 		}
 	}
@@ -235,7 +235,7 @@ func writeCmd(x *BleXport, bl *BleListener, r *BleWriteCmdReq) error {
 			default:
 			}
 
-		case <-bl.AfterTimeout(x.rspTimeout):
+		case <-bl.AfterTimeout(x.RspTimeout()):
 			return BhdTimeoutError(MSG_TYPE_WRITE_CMD)
 		}
 	}
@@ -281,7 +281,7 @@ func exchangeMtu(x *BleXport, bl *BleListener, r *BleExchangeMtuReq) (
 			default:
 			}
 
-		case <-bl.AfterTimeout(x.rspTimeout):
+		case <-bl.AfterTimeout(x.RspTimeout()):
 			return 0, BhdTimeoutError(MSG_TYPE_EXCHANGE_MTU)
 		}
 	}
@@ -320,7 +320,7 @@ func scan(x *BleXport, bl *BleListener, r *BleScanReq,
 			default:
 			}
 
-		case <-bl.AfterTimeout(x.rspTimeout):
+		case <-bl.AfterTimeout(x.RspTimeout()):
 			return BhdTimeoutError(MSG_TYPE_EXCHANGE_MTU)
 
 		case <-abortChan:
@@ -356,7 +356,7 @@ func scanCancel(x *BleXport, bl *BleListener, r *BleScanCancelReq) error {
 			default:
 			}
 
-		case <-bl.AfterTimeout(x.rspTimeout):
+		case <-bl.AfterTimeout(x.RspTimeout()):
 			return BhdTimeoutError(MSG_TYPE_EXCHANGE_MTU)
 		}
 	}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/db639f93/nmxact/nmble/ble_fsm.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_fsm.go b/nmxact/nmble/ble_fsm.go
index cf12bdc..39bfdfc 100644
--- a/nmxact/nmble/ble_fsm.go
+++ b/nmxact/nmble/ble_fsm.go
@@ -216,6 +216,30 @@ func (bf *BleFsm) calcDisconnectType() BleFsmDisconnectType {
 	}
 }
 
+func (bf *BleFsm) onDisconnect(err error) {
+	log.Debugf(err.Error())
+
+	bf.mtx.Lock()
+	bls := make([]*BleListener, 0, len(bf.bls))
+	for bl, _ := range bf.bls {
+		bls = append(bls, bl)
+	}
+	bf.mtx.Unlock()
+
+	// Remember some fields before we clear them.
+	dt := bf.calcDisconnectType()
+	peer := *bf.peerDev
+
+	bf.setState(SESN_STATE_UNCONNECTED)
+	bf.peerDev = nil
+
+	for _, bl := range bls {
+		bl.ErrChan <- err
+	}
+
+	bf.params.DisconnectCb(dt, peer, err)
+}
+
 func (bf *BleFsm) connectListen(seq int) error {
 	bf.connChan = make(chan error, 1)
 
@@ -228,7 +252,10 @@ func (bf *BleFsm) connectListen(seq int) error {
 		defer bf.removeBleSeqListener(seq)
 		for {
 			select {
-			case <-bl.ErrChan:
+			case err := <-bl.ErrChan:
+				// Transport reported error.  Assume all connections have
+				// dropped.
+				bf.onDisconnect(err)
 				return
 
 			case bm := <-bl.BleChan:
@@ -281,33 +308,13 @@ func (bf *BleFsm) connectListen(seq int) error {
 
 				case *BleDisconnectEvt:
 					err := bf.disconnectError(msg.Reason)
-					log.Debugf(err.Error())
-
-					bf.mtx.Lock()
-					bls := make([]*BleListener, 0, len(bf.bls))
-					for bl, _ := range bf.bls {
-						bls = append(bls, bl)
-					}
-					bf.mtx.Unlock()
-
-					// Remember some fields before we clear them.
-					dt := bf.calcDisconnectType()
-					peer := *bf.peerDev
-
-					bf.setState(SESN_STATE_UNCONNECTED)
-					bf.peerDev = nil
-
-					for _, bl := range bls {
-						bl.ErrChan <- err
-					}
-
-					bf.params.DisconnectCb(dt, peer, err)
+					bf.onDisconnect(err)
 					return
 
 				default:
 				}
 
-			case <-bl.AfterTimeout(bf.params.Bx.rspTimeout):
+			case <-bl.AfterTimeout(bf.params.Bx.RspTimeout()):
 				bf.connChan <- BhdTimeoutError(MSG_TYPE_CONNECT)
 			}
 		}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/db639f93/nmxact/nmble/ble_oic_sesn.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_oic_sesn.go b/nmxact/nmble/ble_oic_sesn.go
index 4001960..5fa9291 100644
--- a/nmxact/nmble/ble_oic_sesn.go
+++ b/nmxact/nmble/ble_oic_sesn.go
@@ -5,6 +5,8 @@ import (
 	"sync"
 	"time"
 
+	log "github.com/Sirupsen/logrus"
+
 	"mynewt.apache.org/newt/util"
 	. "mynewt.apache.org/newtmgr/nmxact/bledefs"
 	"mynewt.apache.org/newtmgr/nmxact/nmp"
@@ -135,11 +137,21 @@ func (bos *BleOicSesn) AbortRx(seq uint8) error {
 func (bos *BleOicSesn) Open() error {
 	var err error
 	for i := 0; i < bos.connTries; i++ {
+		log.Debugf("Opening BLE session; try %d/%d", i+1, bos.connTries)
+
 		var retry bool
 		retry, err = bos.bf.Start()
 		if !retry {
 			break
 		}
+
+		if bos.blockUntilClosed(1*time.Second) != nil {
+			// Just close the session manually and report the original error.
+			bos.Close()
+			return err
+		}
+
+		log.Debugf("Connection to BLE peer dropped immediately; retrying")
 	}
 
 	return err

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/db639f93/nmxact/nmble/ble_plain_sesn.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_plain_sesn.go b/nmxact/nmble/ble_plain_sesn.go
index 012a301..15419a9 100644
--- a/nmxact/nmble/ble_plain_sesn.go
+++ b/nmxact/nmble/ble_plain_sesn.go
@@ -5,6 +5,8 @@ import (
 	"sync"
 	"time"
 
+	log "github.com/Sirupsen/logrus"
+
 	"mynewt.apache.org/newt/util"
 	. "mynewt.apache.org/newtmgr/nmxact/bledefs"
 	"mynewt.apache.org/newtmgr/nmxact/nmp"
@@ -128,6 +130,8 @@ func (bps *BlePlainSesn) AbortRx(seq uint8) error {
 func (bps *BlePlainSesn) Open() error {
 	var err error
 	for i := 0; i < bps.connTries; i++ {
+		log.Debugf("Opening BLE session; try %d/%d", i+1, bps.connTries)
+
 		var retry bool
 		retry, err = bps.bf.Start()
 		if !retry {
@@ -139,6 +143,8 @@ func (bps *BlePlainSesn) Open() error {
 			bps.Close()
 			return err
 		}
+
+		log.Debugf("Connection to BLE peer dropped immediately; retrying")
 	}
 
 	return err

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/db639f93/nmxact/nmble/ble_xport.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_xport.go b/nmxact/nmble/ble_xport.go
index ba38b9d..16a4128 100644
--- a/nmxact/nmble/ble_xport.go
+++ b/nmxact/nmble/ble_xport.go
@@ -9,9 +9,9 @@ import (
 
 	log "github.com/Sirupsen/logrus"
 
+	"mynewt.apache.org/newt/util/unixchild"
 	"mynewt.apache.org/newtmgr/nmxact/nmxutil"
 	"mynewt.apache.org/newtmgr/nmxact/sesn"
-	"mynewt.apache.org/newt/util/unixchild"
 )
 
 type XportCfg struct {
@@ -33,13 +33,17 @@ type XportCfg struct {
 
 	// Path of the BLE controller device (e.g., /dev/ttyUSB0).
 	DevPath string
+
+	// How long to allow for the host and controller to sync at startup.
+	SyncTimeout time.Duration
 }
 
 func NewXportCfg() XportCfg {
 	return XportCfg{
 		BlehostdAcceptTimeout: time.Second,
-		BlehostdRestart:       true,
 		BlehostdRspTimeout:    time.Second,
+		BlehostdRestart:       true,
+		SyncTimeout:           10 * time.Second,
 	}
 }
 
@@ -57,31 +61,29 @@ type BleXport struct {
 	client *unixchild.Client
 	state  BleXportState
 
-	syncTimeout time.Duration
-	rspTimeout  time.Duration
+	cfg XportCfg
 }
 
 func NewBleXport(cfg XportCfg) (*BleXport, error) {
-	config := unixchild.Config{
-		SockPath:      cfg.SockPath,
-		ChildPath:     cfg.BlehostdPath,
-		ChildArgs:     []string{cfg.DevPath, cfg.SockPath},
-		Depth:         10,
-		MaxMsgSz:      10240,
-		AcceptTimeout: cfg.BlehostdAcceptTimeout,
-		Restart:       cfg.BlehostdRestart,
+	bx := &BleXport{
+		Bd:  NewBleDispatcher(),
+		cfg: cfg,
 	}
 
-	c := unixchild.New(config)
+	return bx, nil
+}
 
-	bx := &BleXport{
-		client:      c,
-		Bd:          NewBleDispatcher(),
-		syncTimeout: 10 * time.Second,
-		rspTimeout:  cfg.BlehostdRspTimeout,
+func (bx *BleXport) createUnixChild() {
+	config := unixchild.Config{
+		SockPath:      bx.cfg.SockPath,
+		ChildPath:     bx.cfg.BlehostdPath,
+		ChildArgs:     []string{bx.cfg.DevPath, bx.cfg.SockPath},
+		Depth:         10,
+		MaxMsgSz:      10240,
+		AcceptTimeout: bx.cfg.BlehostdAcceptTimeout,
 	}
 
-	return bx, nil
+	bx.client = unixchild.New(config)
 }
 
 func (bx *BleXport) BuildSesn(cfg sesn.SesnCfg) (sesn.Sesn, error) {
@@ -182,11 +184,11 @@ func (bx *BleXport) onError(err error) {
 		// Stop already in progress.
 		return
 	}
-	bx.Bd.ErrorAll(err)
 	if bx.client != nil {
 		bx.client.Stop()
 		bx.client.FromChild <- nil
 	}
+	bx.Bd.ErrorAll(err)
 }
 
 func (bx *BleXport) setStateFrom(from BleXportState, to BleXportState) bool {
@@ -209,24 +211,29 @@ func (bx *BleXport) Start() error {
 		return nmxutil.NewXportError("BLE xport started twice")
 	}
 
+	bx.createUnixChild()
 	if err := bx.client.Start(); err != nil {
-		return nmxutil.NewXportError(
-			"Failed to start child child process: " + err.Error())
+		if unixchild.IsUcAcceptError(err) {
+			err = nmxutil.NewXportError("blehostd did not connect to socket; " +
+				"controller not attached?")
+		} else {
+			err = nmxutil.NewXportError(
+				"Failed to start child process: " + err.Error())
+		}
+		bx.setStateFrom(BLE_XPORT_STATE_STARTING, BLE_XPORT_STATE_STOPPED)
+		return err
 	}
 
 	go func() {
 		err := <-bx.client.ErrChild
-		if unixchild.IsUcAcceptError(err) {
-			err = fmt.Errorf("blehostd did not connect to socket; " +
-				"controller not attached?")
-		}
+		err = nmxutil.NewXportError("BLE transport error: " + err.Error())
+		fmt.Printf("%s\n", err.Error())
 		bx.onError(err)
-		return
 	}()
 
 	go func() {
 		for {
-			if _, err := bx.rx(); err != nil {
+			if b := bx.rx(); b == nil {
 				// The error should have been reported to everyone interested.
 				break
 			}
@@ -254,7 +261,7 @@ func (bx *BleXport) Start() error {
 						break SyncLoop
 					}
 				}
-			case <-time.After(bx.syncTimeout):
+			case <-time.After(bx.cfg.SyncTimeout):
 				bx.Stop()
 				return nmxutil.NewXportError(
 					"Timeout waiting for host <-> controller sync")
@@ -305,15 +312,15 @@ func (bx *BleXport) Tx(data []byte) error {
 	return nil
 }
 
-func (bx *BleXport) rx() ([]byte, error) {
-	select {
-	case err := <-bx.client.ErrChild:
-		return nil, err
-	case buf := <-bx.client.FromChild:
-		if len(buf) != 0 {
-			log.Debugf("Receive from blehostd:\n%s", hex.Dump(buf))
-			bx.Bd.Dispatch(buf)
-		}
-		return buf, nil
+func (bx *BleXport) rx() []byte {
+	buf := <-bx.client.FromChild
+	if len(buf) != 0 {
+		log.Debugf("Receive from blehostd:\n%s", hex.Dump(buf))
+		bx.Bd.Dispatch(buf)
 	}
+	return buf
+}
+
+func (bx *BleXport) RspTimeout() time.Duration {
+	return bx.cfg.BlehostdRspTimeout
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/db639f93/nmxact/nmp/dispatch.go
----------------------------------------------------------------------
diff --git a/nmxact/nmp/dispatch.go b/nmxact/nmp/dispatch.go
index 7b1ad11..5b39a9b 100644
--- a/nmxact/nmp/dispatch.go
+++ b/nmxact/nmp/dispatch.go
@@ -39,6 +39,7 @@ func NewNmpListener() *NmpListener {
 	return &NmpListener{
 		RspChan: make(chan NmpRsp, 1),
 		ErrChan: make(chan error, 1),
+		tmoChan: make(chan time.Time, 1),
 	}
 }
 


[4/6] incubator-mynewt-newtmgr git commit: nmxact - Update ble example.

Posted by cc...@apache.org.
nmxact - Update ble example.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/commit/2f088b4b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/tree/2f088b4b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/diff/2f088b4b

Branch: refs/heads/master
Commit: 2f088b4b40897a8fe01855a1a3d89ec2517ef939
Parents: 2aeb4da
Author: Christopher Collins <cc...@apache.org>
Authored: Mon Apr 3 16:38:21 2017 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Mon Apr 3 16:52:30 2017 -0700

----------------------------------------------------------------------
 nmxact/example/ble_plain/ble_plain.go | 21 ++++++++-------------
 1 file changed, 8 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/2f088b4b/nmxact/example/ble_plain/ble_plain.go
----------------------------------------------------------------------
diff --git a/nmxact/example/ble_plain/ble_plain.go b/nmxact/example/ble_plain/ble_plain.go
index 722083b..a91285c 100644
--- a/nmxact/example/ble_plain/ble_plain.go
+++ b/nmxact/example/ble_plain/ble_plain.go
@@ -31,11 +31,11 @@ import (
 
 func main() {
 	// Initialize the BLE transport.
-	params := nmble.XportCfg{
-		SockPath:     "/tmp/blehostd-uds",
-		BlehostdPath: "blehostd",
-		DevPath:      "/dev/cu.usbserial-A600ANJ1",
-	}
+	params := nmble.NewXportCfg()
+	params.SockPath = "/tmp/blehostd-uds"
+	params.BlehostdPath = "blehostd.elf"
+	params.DevPath = "/dev/cu.usbmodem142111"
+
 	x, err := nmble.NewBleXport(params)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "error creating BLE transport: %s\n",
@@ -52,18 +52,13 @@ func main() {
 	defer x.Stop()
 
 	// Prepare a BLE session:
+	//     * Plain NMP (not tunnelled over OIC).
 	//     * We use a random address.
-	//     * Peer has public address 0b:0a:0b:0a:0b:0a.
+	//     * Peer has name "nimble-bleprph".
 	sc := sesn.NewSesnCfg()
 	sc.MgmtProto = sesn.MGMT_PROTO_NMP
-
 	sc.Ble.OwnAddrType = bledefs.BLE_ADDR_TYPE_RANDOM
-	sc.Ble.PeerSpec = sesn.BlePeerSpecDev(bledefs.BleDev{
-		AddrType: bledefs.BLE_ADDR_TYPE_PUBLIC,
-		Addr: bledefs.BleAddr{
-			Bytes: [6]byte{0x0b, 0x0a, 0x0b, 0x0a, 0x0b, 0x0a},
-		},
-	})
+	sc.Ble.PeerSpec = sesn.BlePeerSpecName("nimble-bleprph")
 
 	s, err := x.BuildSesn(sc)
 	if err != nil {


[5/6] incubator-mynewt-newtmgr git commit: nmxact - Initilize commands with default tx opts.

Posted by cc...@apache.org.
nmxact - Initilize commands with default tx opts.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/commit/d7b0a1a0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/tree/d7b0a1a0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/diff/d7b0a1a0

Branch: refs/heads/master
Commit: d7b0a1a03f73c1f0cf09e5f01ab13655daf24c92
Parents: 2f088b4
Author: Christopher Collins <cc...@apache.org>
Authored: Mon Apr 3 16:47:27 2017 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Mon Apr 3 16:52:30 2017 -0700

----------------------------------------------------------------------
 nmxact/sesn/sesn.go     |  7 +++++++
 nmxact/xact/cmd.go      |  6 ++++++
 nmxact/xact/config.go   |  8 ++++++--
 nmxact/xact/crash.go    |  4 +++-
 nmxact/xact/datetime.go |  8 ++++++--
 nmxact/xact/echo.go     |  4 +++-
 nmxact/xact/fs.go       |  8 ++++++--
 nmxact/xact/image.go    | 24 ++++++++++++++++++------
 nmxact/xact/log.go      | 20 +++++++++++++++-----
 nmxact/xact/mpstat.go   |  4 +++-
 nmxact/xact/reset.go    |  4 +++-
 nmxact/xact/run.go      |  8 ++++++--
 nmxact/xact/stat.go     |  8 ++++++--
 nmxact/xact/taskstat.go |  4 +++-
 14 files changed, 91 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/d7b0a1a0/nmxact/sesn/sesn.go
----------------------------------------------------------------------
diff --git a/nmxact/sesn/sesn.go b/nmxact/sesn/sesn.go
index 8ef8934..0782e63 100644
--- a/nmxact/sesn/sesn.go
+++ b/nmxact/sesn/sesn.go
@@ -12,6 +12,13 @@ type TxOptions struct {
 	Tries   int
 }
 
+func NewTxOptions() TxOptions {
+	return TxOptions{
+		Timeout: 10 * time.Second,
+		Tries:   1,
+	}
+}
+
 func (opt *TxOptions) AfterTimeout() <-chan time.Time {
 	if opt.Timeout == 0 {
 		return nil

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/d7b0a1a0/nmxact/xact/cmd.go
----------------------------------------------------------------------
diff --git a/nmxact/xact/cmd.go b/nmxact/xact/cmd.go
index d5d7a23..9bc3728 100644
--- a/nmxact/xact/cmd.go
+++ b/nmxact/xact/cmd.go
@@ -45,6 +45,12 @@ type CmdBase struct {
 	abortErr  error
 }
 
+func NewCmdBase() CmdBase {
+	return CmdBase{
+		txOptions: sesn.NewTxOptions(),
+	}
+}
+
 func (c *CmdBase) TxOptions() sesn.TxOptions {
 	return c.txOptions
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/d7b0a1a0/nmxact/xact/config.go
----------------------------------------------------------------------
diff --git a/nmxact/xact/config.go b/nmxact/xact/config.go
index ddc893b..fc55505 100644
--- a/nmxact/xact/config.go
+++ b/nmxact/xact/config.go
@@ -15,7 +15,9 @@ type ConfigReadCmd struct {
 }
 
 func NewConfigReadCmd() *ConfigReadCmd {
-	return &ConfigReadCmd{}
+	return &ConfigReadCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type ConfigReadResult struct {
@@ -56,7 +58,9 @@ type ConfigWriteCmd struct {
 }
 
 func NewConfigWriteCmd() *ConfigWriteCmd {
-	return &ConfigWriteCmd{}
+	return &ConfigWriteCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type ConfigWriteResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/d7b0a1a0/nmxact/xact/crash.go
----------------------------------------------------------------------
diff --git a/nmxact/xact/crash.go b/nmxact/xact/crash.go
index ebb94c7..f665c88 100644
--- a/nmxact/xact/crash.go
+++ b/nmxact/xact/crash.go
@@ -56,7 +56,9 @@ type CrashCmd struct {
 }
 
 func NewCrashCmd() *CrashCmd {
-	return &CrashCmd{}
+	return &CrashCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type CrashResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/d7b0a1a0/nmxact/xact/datetime.go
----------------------------------------------------------------------
diff --git a/nmxact/xact/datetime.go b/nmxact/xact/datetime.go
index 27bd089..f6622df 100644
--- a/nmxact/xact/datetime.go
+++ b/nmxact/xact/datetime.go
@@ -14,7 +14,9 @@ type DateTimeReadCmd struct {
 }
 
 func NewDateTimeReadCmd() *DateTimeReadCmd {
-	return &DateTimeReadCmd{}
+	return &DateTimeReadCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type DateTimeReadResult struct {
@@ -53,7 +55,9 @@ type DateTimeWriteCmd struct {
 }
 
 func NewDateTimeWriteCmd() *DateTimeWriteCmd {
-	return &DateTimeWriteCmd{}
+	return &DateTimeWriteCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type DateTimeWriteResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/d7b0a1a0/nmxact/xact/echo.go
----------------------------------------------------------------------
diff --git a/nmxact/xact/echo.go b/nmxact/xact/echo.go
index 09622b2..630e876 100644
--- a/nmxact/xact/echo.go
+++ b/nmxact/xact/echo.go
@@ -11,7 +11,9 @@ type EchoCmd struct {
 }
 
 func NewEchoCmd() *EchoCmd {
-	return &EchoCmd{}
+	return &EchoCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type EchoResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/d7b0a1a0/nmxact/xact/fs.go
----------------------------------------------------------------------
diff --git a/nmxact/xact/fs.go b/nmxact/xact/fs.go
index 0fe32c6..c6668de 100644
--- a/nmxact/xact/fs.go
+++ b/nmxact/xact/fs.go
@@ -19,7 +19,9 @@ type FsDownloadCmd struct {
 }
 
 func NewFsDownloadCmd() *FsDownloadCmd {
-	return &FsDownloadCmd{}
+	return &FsDownloadCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type FsDownloadResult struct {
@@ -81,7 +83,9 @@ type FsUploadCmd struct {
 }
 
 func NewFsUploadCmd() *FsUploadCmd {
-	return &FsUploadCmd{}
+	return &FsUploadCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type FsUploadResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/d7b0a1a0/nmxact/xact/image.go
----------------------------------------------------------------------
diff --git a/nmxact/xact/image.go b/nmxact/xact/image.go
index 615dd74..55ba44c 100644
--- a/nmxact/xact/image.go
+++ b/nmxact/xact/image.go
@@ -23,7 +23,9 @@ type ImageUploadResult struct {
 }
 
 func NewImageUploadCmd() *ImageUploadCmd {
-	return &ImageUploadCmd{}
+	return &ImageUploadCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 func newImageUploadResult() *ImageUploadResult {
@@ -127,7 +129,9 @@ type ImageStateReadResult struct {
 }
 
 func NewImageStateReadCmd() *ImageStateReadCmd {
-	return &ImageStateReadCmd{}
+	return &ImageStateReadCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 func newImageStateReadResult() *ImageStateReadResult {
@@ -167,7 +171,9 @@ type ImageStateWriteResult struct {
 }
 
 func NewImageStateWriteCmd() *ImageStateWriteCmd {
-	return &ImageStateWriteCmd{}
+	return &ImageStateWriteCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 func newImageStateWriteResult() *ImageStateWriteResult {
@@ -207,7 +213,9 @@ type CoreListResult struct {
 }
 
 func NewCoreListCmd() *CoreListCmd {
-	return &CoreListCmd{}
+	return &CoreListCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 func newCoreListResult() *CoreListResult {
@@ -247,7 +255,9 @@ type CoreLoadResult struct {
 }
 
 func NewCoreLoadCmd() *CoreLoadCmd {
-	return &CoreLoadCmd{}
+	return &CoreLoadCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 func newCoreLoadResult() *CoreLoadResult {
@@ -306,7 +316,9 @@ type CoreEraseResult struct {
 }
 
 func NewCoreEraseCmd() *CoreEraseCmd {
-	return &CoreEraseCmd{}
+	return &CoreEraseCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 func newCoreEraseResult() *CoreEraseResult {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/d7b0a1a0/nmxact/xact/log.go
----------------------------------------------------------------------
diff --git a/nmxact/xact/log.go b/nmxact/xact/log.go
index 86b348f..f71f8a3 100644
--- a/nmxact/xact/log.go
+++ b/nmxact/xact/log.go
@@ -17,7 +17,9 @@ type LogShowCmd struct {
 }
 
 func NewLogShowCmd() *LogShowCmd {
-	return &LogShowCmd{}
+	return &LogShowCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type LogShowResult struct {
@@ -58,7 +60,9 @@ type LogListCmd struct {
 }
 
 func NewLogListCmd() *LogListCmd {
-	return &LogListCmd{}
+	return &LogListCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type LogListResult struct {
@@ -96,7 +100,9 @@ type LogModuleListCmd struct {
 }
 
 func NewLogModuleListCmd() *LogModuleListCmd {
-	return &LogModuleListCmd{}
+	return &LogModuleListCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type LogModuleListResult struct {
@@ -134,7 +140,9 @@ type LogLevelListCmd struct {
 }
 
 func NewLogLevelListCmd() *LogLevelListCmd {
-	return &LogLevelListCmd{}
+	return &LogLevelListCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type LogLevelListResult struct {
@@ -172,7 +180,9 @@ type LogClearCmd struct {
 }
 
 func NewLogClearCmd() *LogClearCmd {
-	return &LogClearCmd{}
+	return &LogClearCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type LogClearResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/d7b0a1a0/nmxact/xact/mpstat.go
----------------------------------------------------------------------
diff --git a/nmxact/xact/mpstat.go b/nmxact/xact/mpstat.go
index acff3e2..cb7b0da 100644
--- a/nmxact/xact/mpstat.go
+++ b/nmxact/xact/mpstat.go
@@ -10,7 +10,9 @@ type MempoolStatCmd struct {
 }
 
 func NewMempoolStatCmd() *MempoolStatCmd {
-	return &MempoolStatCmd{}
+	return &MempoolStatCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type MempoolStatResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/d7b0a1a0/nmxact/xact/reset.go
----------------------------------------------------------------------
diff --git a/nmxact/xact/reset.go b/nmxact/xact/reset.go
index 397ad60..08a1040 100644
--- a/nmxact/xact/reset.go
+++ b/nmxact/xact/reset.go
@@ -11,7 +11,9 @@ type ResetCmd struct {
 }
 
 func NewResetCmd() *ResetCmd {
-	return &ResetCmd{}
+	return &ResetCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type ResetResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/d7b0a1a0/nmxact/xact/run.go
----------------------------------------------------------------------
diff --git a/nmxact/xact/run.go b/nmxact/xact/run.go
index 28d71a9..d1af353 100644
--- a/nmxact/xact/run.go
+++ b/nmxact/xact/run.go
@@ -16,7 +16,9 @@ type RunTestCmd struct {
 }
 
 func NewRunTestCmd() *RunTestCmd {
-	return &RunTestCmd{}
+	return &RunTestCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type RunTestResult struct {
@@ -56,7 +58,9 @@ type RunListCmd struct {
 }
 
 func NewRunListCmd() *RunListCmd {
-	return &RunListCmd{}
+	return &RunListCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type RunListResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/d7b0a1a0/nmxact/xact/stat.go
----------------------------------------------------------------------
diff --git a/nmxact/xact/stat.go b/nmxact/xact/stat.go
index a38eba9..f921afa 100644
--- a/nmxact/xact/stat.go
+++ b/nmxact/xact/stat.go
@@ -15,7 +15,9 @@ type StatReadCmd struct {
 }
 
 func NewStatReadCmd() *StatReadCmd {
-	return &StatReadCmd{}
+	return &StatReadCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type StatReadResult struct {
@@ -54,7 +56,9 @@ type StatListCmd struct {
 }
 
 func NewStatListCmd() *StatListCmd {
-	return &StatListCmd{}
+	return &StatListCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type StatListResult struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/d7b0a1a0/nmxact/xact/taskstat.go
----------------------------------------------------------------------
diff --git a/nmxact/xact/taskstat.go b/nmxact/xact/taskstat.go
index bb03357..a2e82c4 100644
--- a/nmxact/xact/taskstat.go
+++ b/nmxact/xact/taskstat.go
@@ -10,7 +10,9 @@ type TaskStatCmd struct {
 }
 
 func NewTaskStatCmd() *TaskStatCmd {
-	return &TaskStatCmd{}
+	return &TaskStatCmd{
+		CmdBase: NewCmdBase(),
+	}
 }
 
 type TaskStatResult struct {