@@ -30,19 +30,20 @@ type pState struct {
3030 stdinPipe streamIn
3131 stdoutPipe io.ReadCloser
3232 stderrPipe io.ReadCloser
33+ exitStatus * int
34+ waitChan chan int
3335}
3436
3537type jsonBasedHyperstart struct {
3638 sync.RWMutex
37- logPrefix string
38- vmAPIVersion uint32
39- closed bool
40- lastStreamSeq uint64
41- procs map [pKey ]* pState
42- streamOuts map [uint64 ]streamOut
43- ctlChan chan * hyperstartCmd
44- streamChan chan * hyperstartapi.TtyMessage
45- processAsyncEvents chan hyperstartapi.ProcessAsyncEvent
39+ logPrefix string
40+ vmAPIVersion uint32
41+ closed bool
42+ lastStreamSeq uint64
43+ procs map [pKey ]* pState
44+ streamOuts map [uint64 ]streamOut
45+ ctlChan chan * hyperstartCmd
46+ streamChan chan * hyperstartapi.TtyMessage
4647}
4748
4849type hyperstartCmd struct {
@@ -56,13 +57,12 @@ type hyperstartCmd struct {
5657
5758func NewJsonBasedHyperstart (id , ctlSock , streamSock string , lastStreamSeq uint64 , waitReady bool ) Hyperstart {
5859 h := & jsonBasedHyperstart {
59- logPrefix : fmt .Sprintf ("SB[%s] " , id ),
60- procs : make (map [pKey ]* pState ),
61- lastStreamSeq : lastStreamSeq ,
62- streamOuts : make (map [uint64 ]streamOut ),
63- ctlChan : make (chan * hyperstartCmd , 128 ),
64- streamChan : make (chan * hyperstartapi.TtyMessage , 128 ),
65- processAsyncEvents : make (chan hyperstartapi.ProcessAsyncEvent , 16 ),
60+ logPrefix : fmt .Sprintf ("SB[%s] " , id ),
61+ procs : make (map [pKey ]* pState ),
62+ lastStreamSeq : lastStreamSeq ,
63+ streamOuts : make (map [uint64 ]streamOut ),
64+ ctlChan : make (chan * hyperstartCmd , 128 ),
65+ streamChan : make (chan * hyperstartapi.TtyMessage , 128 ),
6666 }
6767 go handleStreamSock (h , streamSock )
6868 go handleCtlSock (h , ctlSock , waitReady )
@@ -86,8 +86,9 @@ func (h *jsonBasedHyperstart) Close() {
8686 defer h .Unlock ()
8787 if ! h .closed {
8888 h .Log (TRACE , "close jsonBasedHyperstart" )
89- for pk := range h .procs {
90- h .processAsyncEvents <- hyperstartapi.ProcessAsyncEvent {Container : pk .c , Process : pk .p , Event : "finished" , Status : 255 }
89+ for pk , ps := range h .procs {
90+ ps .exitStatus = makeExitStatus (255 )
91+ h .handleWaitProcess (pk , ps )
9192 }
9293 h .procs = make (map [pKey ]* pState )
9394 for _ , out := range h .streamOuts {
@@ -96,7 +97,6 @@ func (h *jsonBasedHyperstart) Close() {
9697 h .streamOuts = make (map [uint64 ]streamOut )
9798 close (h .ctlChan )
9899 close (h .streamChan )
99- close (h .processAsyncEvents )
100100 for cmd := range h .ctlChan {
101101 if cmd .Code != hyperstartapi .INIT_ACK && cmd .Code != hyperstartapi .INIT_ERROR {
102102 cmd .result <- fmt .Errorf ("hyperstart closed" )
@@ -106,10 +106,6 @@ func (h *jsonBasedHyperstart) Close() {
106106 }
107107}
108108
109- func (h * jsonBasedHyperstart ) ProcessAsyncEvents () (<- chan hyperstartapi.ProcessAsyncEvent , error ) {
110- return h .processAsyncEvents , nil
111- }
112-
113109func (h * jsonBasedHyperstart ) LastStreamSeq () uint64 {
114110 return h .lastStreamSeq
115111}
@@ -459,13 +455,22 @@ func handleStreamFromHyperstart(h *jsonBasedHyperstart, conn io.Reader) {
459455 }
460456}
461457
458+ func makeExitStatus (status int ) * int { return & status }
459+
460+ func (h * jsonBasedHyperstart ) handleWaitProcess (pk pKey , ps * pState ) {
461+ if ps .exitStatus != nil && ps .waitChan != nil {
462+ delete (h .procs , pk )
463+ ps .waitChan <- * ps .exitStatus
464+ }
465+ }
466+
462467func (h * jsonBasedHyperstart ) sendProcessAsyncEvent (pae hyperstartapi.ProcessAsyncEvent ) {
463468 h .Lock ()
464469 defer h .Unlock ()
465470 pk := pKey {c : pae .Container , p : pae .Process }
466- if _ , ok := h .procs [pk ]; ok {
467- delete ( h . procs , pk )
468- h .processAsyncEvents <- pae
471+ if ps , ok := h .procs [pk ]; ok {
472+ ps . exitStatus = makeExitStatus ( pae . Status )
473+ h .handleWaitProcess ( pk , ps )
469474 }
470475}
471476
@@ -474,8 +479,8 @@ func (h *jsonBasedHyperstart) sendProcessAsyncEvent4242(stdioSeq uint64, code ui
474479 defer h .Unlock ()
475480 for pk , ps := range h .procs {
476481 if ps .stdioSeq == stdioSeq {
477- delete ( h . procs , pk )
478- h .processAsyncEvents <- hyperstartapi. ProcessAsyncEvent { Container : pk . c , Process : pk . p , Event : "finished" , Status : int ( code )}
482+ ps . exitStatus = makeExitStatus ( int ( code ) )
483+ h .handleWaitProcess ( pk , ps )
479484 }
480485 }
481486}
@@ -752,6 +757,26 @@ func (h *jsonBasedHyperstart) SignalProcess(container, process string, signal sy
752757 })
753758}
754759
760+ // wait the process until exit. like waitpid()
761+ // the state is saved until someone calls WaitProcess() if the process exited earlier
762+ // the non-first call of WaitProcess() after process started MAY fail to find the process if the process exited earlier
763+ func (h * jsonBasedHyperstart ) WaitProcess (container , process string ) int {
764+ h .Lock ()
765+ pk := pKey {c : container , p : process }
766+ if ps , ok := h .procs [pk ]; ok {
767+ if ps .waitChan == nil {
768+ ps .waitChan = make (chan int , 1 )
769+ h .handleWaitProcess (pk , ps )
770+ }
771+ h .Unlock ()
772+ status := <- ps .waitChan
773+ ps .waitChan <- status
774+ return status
775+ }
776+ h .Unlock ()
777+ return - 1
778+ }
779+
755780func (h * jsonBasedHyperstart ) StartSandbox (pod * hyperstartapi.Pod ) error {
756781 return h .hyperstartCommand (hyperstartapi .INIT_STARTPOD , pod )
757782}
0 commit comments