fix a deadlock

This commit is contained in:
Zhi Wang 2022-01-09 22:23:52 -05:00
parent 0f76aeef8d
commit 598e01c1e9
2 changed files with 12 additions and 8 deletions

5
reg.go
View File

@ -24,8 +24,9 @@ func (reg *Registry) init() {
func (d *Registry) addDoer(name string, tc *TermConn) { func (d *Registry) addDoer(name string, tc *TermConn) {
d.mtx.Lock() d.mtx.Lock()
if val, ok := d.doers[name]; ok { if val, ok := d.doers[name]; ok {
log.Printf(name, "already exist in the dispatcher") log.Println(name, "already exist in the dispatcher", val, tc)
val.release() delete(d.doers, name)
val.release(false) // do not unregister in release, otherwise it is a deadlock
} }
d.doers[name] = tc d.doers[name] = tc
d.mtx.Unlock() d.mtx.Unlock()

View File

@ -159,10 +159,10 @@ func (tc *TermConn) ptyStdoutToWs() {
// handle viewers, we want to use non-blocking receive // handle viewers, we want to use non-blocking receive
select { select {
case watcher := <-tc.vchan: case watcher := <-tc.vchan:
log.Println("Received watcher", watcher) log.Println("Received viewer", watcher)
viewers = append(viewers, watcher) viewers = append(viewers, watcher)
default: default:
log.Println("no watcher received") //log.Println("no viewer received")
} }
// We could add ws to viewers as well (then we can use io.MultiWriter), // We could add ws to viewers as well (then we can use io.MultiWriter),
@ -195,15 +195,19 @@ func (tc *TermConn) ptyStdoutToWs() {
} }
} }
close(tc.done)
tc.ws.SetWriteDeadline(time.Now().Add(writeWait)) tc.ws.SetWriteDeadline(time.Now().Add(writeWait))
tc.ws.WriteMessage(websocket.CloseMessage, tc.ws.WriteMessage(websocket.CloseMessage,
websocket.FormatCloseMessage(websocket.CloseNormalClosure, "Pty closed")) websocket.FormatCloseMessage(websocket.CloseNormalClosure, "Pty closed"))
time.Sleep(closeGracePeriod) time.Sleep(closeGracePeriod)
} }
func (tc *TermConn) release() { func (tc *TermConn) release(unreg bool) {
log.Println("releasing", tc.name) log.Println("releasing", tc.name)
if unreg {
registry.delDoer(tc.name) registry.delDoer(tc.name)
}
if tc.ptmx != nil { if tc.ptmx != nil {
// cleanup the pty and its related process // cleanup the pty and its related process
@ -231,7 +235,6 @@ func (tc *TermConn) release() {
log.Printf("Failed to wait for shell process(%v): %v", proc.Pid, err) log.Printf("Failed to wait for shell process(%v): %v", proc.Pid, err)
} }
close(tc.done)
close(tc.vchan) close(tc.vchan)
} }
@ -253,7 +256,7 @@ func wsHandleDoer(w http.ResponseWriter, r *http.Request) {
name: "main", name: "main",
} }
defer tc.release() defer tc.release(true)
log.Println("\n\nCreated the websocket") log.Println("\n\nCreated the websocket")
if err := tc.createPty(cmdToExec); err != nil { if err := tc.createPty(cmdToExec); err != nil {