@@ -30,19 +30,21 @@ type pState struct {
3030 stdinPipe streamIn
3131 stdoutPipe io.ReadCloser
3232 stderrPipe io.ReadCloser
33+ exitStatus * int
34+ outClosed bool
35+ waitChan chan int
3336}
3437
3538type jsonBasedHyperstart struct {
3639 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
40+ logPrefix string
41+ vmAPIVersion uint32
42+ closed bool
43+ lastStreamSeq uint64
44+ procs map [pKey ]* pState
45+ streamOuts map [uint64 ]streamOut
46+ ctlChan chan * hyperstartCmd
47+ streamChan chan * hyperstartapi.TtyMessage
4648}
4749
4850type hyperstartCmd struct {
@@ -56,13 +58,12 @@ type hyperstartCmd struct {
5658
5759func NewJsonBasedHyperstart (id , ctlSock , streamSock string , lastStreamSeq uint64 , waitReady bool ) Hyperstart {
5860 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 ),
61+ logPrefix : fmt .Sprintf ("SB[%s] " , id ),
62+ procs : make (map [pKey ]* pState ),
63+ lastStreamSeq : lastStreamSeq ,
64+ streamOuts : make (map [uint64 ]streamOut ),
65+ ctlChan : make (chan * hyperstartCmd , 128 ),
66+ streamChan : make (chan * hyperstartapi.TtyMessage , 128 ),
6667 }
6768 go handleStreamSock (h , streamSock )
6869 go handleCtlSock (h , ctlSock , waitReady )
@@ -86,17 +87,18 @@ func (h *jsonBasedHyperstart) Close() {
8687 defer h .Unlock ()
8788 if ! h .closed {
8889 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 }
91- }
92- h .procs = make (map [pKey ]* pState )
9390 for _ , out := range h .streamOuts {
9491 out .Close ()
9592 }
9693 h .streamOuts = make (map [uint64 ]streamOut )
94+ for pk , ps := range h .procs {
95+ ps .outClosed = true
96+ ps .exitStatus = makeExitStatus (255 )
97+ h .handleWaitProcess (pk , ps )
98+ }
99+ h .procs = make (map [pKey ]* pState )
97100 close (h .ctlChan )
98101 close (h .streamChan )
99- close (h .processAsyncEvents )
100102 for cmd := range h .ctlChan {
101103 if cmd .Code != hyperstartapi .INIT_ACK && cmd .Code != hyperstartapi .INIT_ERROR {
102104 cmd .result <- fmt .Errorf ("hyperstart closed" )
@@ -106,10 +108,6 @@ func (h *jsonBasedHyperstart) Close() {
106108 }
107109}
108110
109- func (h * jsonBasedHyperstart ) ProcessAsyncEvents () (<- chan hyperstartapi.ProcessAsyncEvent , error ) {
110- return h .processAsyncEvents , nil
111- }
112-
113111func (h * jsonBasedHyperstart ) LastStreamSeq () uint64 {
114112 return h .lastStreamSeq
115113}
@@ -458,13 +456,22 @@ func handleStreamFromHyperstart(h *jsonBasedHyperstart, conn io.Reader) {
458456 }
459457}
460458
459+ func makeExitStatus (status int ) * int { return & status }
460+
461+ func (h * jsonBasedHyperstart ) handleWaitProcess (pk pKey , ps * pState ) {
462+ if ps .exitStatus != nil && ps .waitChan != nil && ps .outClosed {
463+ delete (h .procs , pk )
464+ ps .waitChan <- * ps .exitStatus
465+ }
466+ }
467+
461468func (h * jsonBasedHyperstart ) sendProcessAsyncEvent (pae hyperstartapi.ProcessAsyncEvent ) {
462469 h .Lock ()
463470 defer h .Unlock ()
464471 pk := pKey {c : pae .Container , p : pae .Process }
465- if _ , ok := h .procs [pk ]; ok {
466- delete ( h . procs , pk )
467- h .processAsyncEvents <- pae
472+ if ps , ok := h .procs [pk ]; ok {
473+ ps . exitStatus = makeExitStatus ( pae . Status )
474+ h .handleWaitProcess ( pk , ps )
468475 }
469476}
470477
@@ -473,8 +480,8 @@ func (h *jsonBasedHyperstart) sendProcessAsyncEvent4242(stdioSeq uint64, code ui
473480 defer h .Unlock ()
474481 for pk , ps := range h .procs {
475482 if ps .stdioSeq == stdioSeq {
476- delete ( h . procs , pk )
477- h .processAsyncEvents <- hyperstartapi. ProcessAsyncEvent { Container : pk . c , Process : pk . p , Event : "finished" , Status : int ( code )}
483+ ps . exitStatus = makeExitStatus ( int ( code ) )
484+ h .handleWaitProcess ( pk , ps )
478485 }
479486 }
480487}
@@ -486,8 +493,17 @@ func (h *jsonBasedHyperstart) removeStreamOut(seq uint64) {
486493 // doesn't send eof of the stderr back, so we also remove stderr seq here
487494 if out , ok := h .streamOuts [seq ]; ok {
488495 delete (h .streamOuts , seq )
489- if seq == out .ps .stdioSeq && out .ps .stderrSeq > 0 {
490- delete (h .streamOuts , out .ps .stderrSeq )
496+ if seq == out .ps .stdioSeq {
497+ if out .ps .stderrSeq > 0 {
498+ h .streamOuts [out .ps .stderrSeq ].Close ()
499+ delete (h .streamOuts , out .ps .stderrSeq )
500+ }
501+ for pk , ps := range h .procs {
502+ if ps .stdioSeq == seq {
503+ ps .outClosed = true
504+ h .handleWaitProcess (pk , ps )
505+ }
506+ }
491507 }
492508 }
493509}
@@ -751,6 +767,26 @@ func (h *jsonBasedHyperstart) SignalProcess(container, process string, signal sy
751767 })
752768}
753769
770+ // wait the process until exit. like waitpid()
771+ // the state is saved until someone calls WaitProcess() if the process exited earlier
772+ // the non-first call of WaitProcess() after process started MAY fail to find the process if the process exited earlier
773+ func (h * jsonBasedHyperstart ) WaitProcess (container , process string ) int {
774+ h .Lock ()
775+ pk := pKey {c : container , p : process }
776+ if ps , ok := h .procs [pk ]; ok {
777+ if ps .waitChan == nil {
778+ ps .waitChan = make (chan int , 1 )
779+ h .handleWaitProcess (pk , ps )
780+ }
781+ h .Unlock ()
782+ status := <- ps .waitChan
783+ ps .waitChan <- status
784+ return status
785+ }
786+ h .Unlock ()
787+ return - 1
788+ }
789+
754790func (h * jsonBasedHyperstart ) StartSandbox (pod * hyperstartapi.Pod ) error {
755791 return h .hyperstartCommand (hyperstartapi .INIT_STARTPOD , pod )
756792}
0 commit comments