-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement a session handle to running processes
- Implement Start function that returns a Session - Change Run to use Start and Session#Wait - Replace RunStatus with Session FAB-16108 Change-Id: I1ed90b9452c43020bd3a99904b6089ad6fb22b09 Signed-off-by: Matthew Sykes <[email protected]>
- Loading branch information
Showing
7 changed files
with
211 additions
and
120 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
Copyright IBM Corp. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package externalbuilders | ||
|
||
import ( | ||
"bufio" | ||
"io" | ||
"os" | ||
"os/exec" | ||
"path/filepath" | ||
"sync" | ||
"syscall" | ||
|
||
"github.com/hyperledger/fabric/common/flogging" | ||
) | ||
|
||
type Session struct { | ||
mutex sync.Mutex | ||
command *exec.Cmd | ||
exited chan struct{} | ||
exitErr error | ||
waitStatus syscall.WaitStatus | ||
} | ||
|
||
// Start will start the provided command and return a Session that can be used | ||
// to await completion or signal the process. | ||
// | ||
// The provided logger is used log stderr from the running process. | ||
func Start(logger *flogging.FabricLogger, cmd *exec.Cmd) (*Session, error) { | ||
logger = logger.With("command", filepath.Base(cmd.Path)) | ||
|
||
stderr, err := cmd.StderrPipe() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
err = cmd.Start() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
sess := &Session{ | ||
command: cmd, | ||
exited: make(chan struct{}), | ||
} | ||
go sess.waitForExit(logger, stderr) | ||
|
||
return sess, nil | ||
} | ||
|
||
func (s *Session) waitForExit(logger *flogging.FabricLogger, stderr io.Reader) { | ||
// copy stderr to the logger until stderr is closed | ||
scanner := bufio.NewScanner(stderr) | ||
for scanner.Scan() { | ||
logger.Info(scanner.Text()) | ||
} | ||
if err := scanner.Err(); err != nil { | ||
logger.Errorf("command output scanning failed: %s", err) | ||
} | ||
|
||
// wait for the command to exit and to complete | ||
err := s.command.Wait() | ||
|
||
// update state and close the exited channel | ||
s.mutex.Lock() | ||
defer s.mutex.Unlock() | ||
s.exitErr = err | ||
s.waitStatus = s.command.ProcessState.Sys().(syscall.WaitStatus) | ||
close(s.exited) | ||
} | ||
|
||
// Wait waits for the running command to terminate and returns the exit error | ||
// from the command. If the command has already exited, the exit err will be | ||
// returned immediately. | ||
func (s *Session) Wait() error { | ||
<-s.exited | ||
return s.exitErr | ||
} | ||
|
||
// Signal will send a signal to the running process. | ||
func (s *Session) Signal(sig os.Signal) { | ||
s.command.Process.Signal(sig) | ||
} |
Oops, something went wrong.