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:38 UTC

[1/3] incubator-mynewt-newt git commit: unixchild - prevent half-started state

Repository: incubator-mynewt-newt
Updated Branches:
  refs/heads/develop df674371e -> 9de7460f1


unixchild - prevent half-started state

This fix consists of two parts:

1. Remove thread-safety where it is not necessary.  There weren't any
bugs here, but it was complicating the code needlessly.

2. Don't automatically restart the child process when it terminates.  It
is up to the client to do this.


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

Branch: refs/heads/develop
Commit: 1a0a9ef725ab6ce5ba41855f4b681deae61f952c
Parents: df67437
Author: Christopher Collins <cc...@apache.org>
Authored: Fri Mar 31 16:42:41 2017 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Fri Mar 31 16:42:41 2017 -0700

----------------------------------------------------------------------
 util/unixchild/unixchild.go | 128 ++++++++++++---------------------------
 1 file changed, 39 insertions(+), 89 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/1a0a9ef7/util/unixchild/unixchild.go
----------------------------------------------------------------------
diff --git a/util/unixchild/unixchild.go b/util/unixchild/unixchild.go
index b8be35d..b417187 100644
--- a/util/unixchild/unixchild.go
+++ b/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,18 @@ 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.state = CLIENT_STATE_STOPPED
 		log.Debugf("Stopped client")
 		return
 	}
@@ -277,63 +234,56 @@ 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)
 		return err
 	}
 
-	var cmd *exec.Cmd
+	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
+	}
+
+	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


[3/3] incubator-mynewt-newt git commit: unixchild - Ensure socket gets deleted on stop.

Posted by cc...@apache.org.
unixchild - Ensure socket gets deleted on stop.


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

Branch: refs/heads/develop
Commit: 9de7460f1fc510d724a507692abcd8e45f9e5f02
Parents: 74d8512
Author: Christopher Collins <cc...@apache.org>
Authored: Mon Apr 3 16:48:20 2017 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Mon Apr 3 16:53:26 2017 -0700

----------------------------------------------------------------------
 util/unixchild/unixchild.go | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/9de7460f/util/unixchild/unixchild.go
----------------------------------------------------------------------
diff --git a/util/unixchild/unixchild.go b/util/unixchild/unixchild.go
index b417187..91930c0 100644
--- a/util/unixchild/unixchild.go
+++ b/util/unixchild/unixchild.go
@@ -219,6 +219,7 @@ func (c *Client) Stop() {
 
 	select {
 	case <-c.stopped:
+		c.deleteSocket()
 		c.state = CLIENT_STATE_STOPPED
 		log.Debugf("Stopped client")
 		return
@@ -246,6 +247,7 @@ func (c *Client) Start() error {
 
 	l, err := net.Listen("unix", c.sockPath)
 	if err != nil {
+		c.deleteSocket()
 		return err
 	}
 


[2/3] incubator-mynewt-newt git commit: Add PrintStacks util function.

Posted by cc...@apache.org.
Add PrintStacks util function.


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

Branch: refs/heads/develop
Commit: 74d851283af3c31e79cd6f0432c0aa02d93c13f5
Parents: 1a0a9ef
Author: Christopher Collins <cc...@apache.org>
Authored: Fri Mar 31 17:07:54 2017 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Fri Mar 31 17:07:54 2017 -0700

----------------------------------------------------------------------
 util/util.go | 6 ++++++
 1 file changed, 6 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/74d85128/util/util.go
----------------------------------------------------------------------
diff --git a/util/util.go b/util/util.go
index fa3e60f..3e144e6 100644
--- a/util/util.go
+++ b/util/util.go
@@ -620,3 +620,9 @@ func IntMin(a, b int) int {
 		return b
 	}
 }
+
+func PrintStacks() {
+	buf := make([]byte, 1024*1024)
+	stacklen := runtime.Stack(buf, true)
+	fmt.Printf("*** goroutine dump\n%s\n*** end\n", buf[:stacklen])
+}