Skip to content

Commit

Permalink
cmd/acme: fix undo, fix wait chan mostly
Browse files Browse the repository at this point in the history
Edit |date still hangs.
  • Loading branch information
rsc committed Oct 5, 2021
1 parent 1008b83 commit 0b266bf
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 41 deletions.
38 changes: 21 additions & 17 deletions cmd/acme/acme.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ func main() {

ui.Textcomplete = fileloadpkg.Textcomplete
editpkg.Putfile = exec.Putfile
editpkg.BigLock = bigLock
editpkg.BigUnlock = bigUnlock
editpkg.Run = func(w *wind.Window, s string, rdir []rune) {
exec.Run(w, s, rdir, true, nil, nil, true)
}
Expand Down Expand Up @@ -583,14 +585,14 @@ func mousethread() {
* This structure keeps a list of processes that have exited we haven't heard of.
*/

type Pid struct {
pid int
msg string
next *Pid
type Proc struct {
proc *os.Process
err error
next *Proc
}

func waitthread() {
var pids *Pid
var pids *Proc

bigLock()
defer bigUnlock()
Expand Down Expand Up @@ -624,12 +626,13 @@ func waitthread() {
alog.Printf("Kill: no process %s\n", string(cmd))
}

case w := <-cwait:
case w := <-exec.Cwait:
println("Cwait")
bigLock()
pid := w.pid
proc := w.Proc
var c, lc *exec.Command
for c = command; c != nil; c = c.Next {
if c.Pid == pid {
if c.Proc == proc {
if lc != nil {
lc.Next = c.Next
} else {
Expand All @@ -643,18 +646,18 @@ func waitthread() {
t := &wind.TheRow.Tag
wind.Textcommit(t, true)
if c == nil {
p := new(Pid)
p.pid = pid
p.msg = w.msg
p := new(Proc)
p.proc = proc
p.err = w.Err
p.next = pids
pids = p
} else {
if ui.Search(t, c.Name) {
wind.Textdelete(t, t.Q0, t.Q1, true)
wind.Textsetselect(t, 0, 0)
}
if w.msg[0] != 0 {
warning(c.Mntdir, "%s: exit %s\n", string(c.Name[:len(c.Name)-1]), w.msg)
if w.Err != nil {
warning(c.Mntdir, "%s: exit %s\n", string(c.Name[:len(c.Name)-1]), w.Err)
}
adraw.Display.Flush()
}
Expand All @@ -664,11 +667,11 @@ func waitthread() {
case c = <-exec.Ccommand:
bigLock()
// has this command already exited?
var lastp *Pid
var lastp *Proc
for p := pids; p != nil; p = p.next {
if p.pid == c.Pid {
if p.msg[0] != 0 {
warning(c.Mntdir, "%s\n", p.msg)
if p.proc == c.Proc {
if p.err != nil {
warning(c.Mntdir, "%s\n", p.err)
}
if lastp == nil {
pids = p.next
Expand All @@ -694,6 +697,7 @@ func waitthread() {
Freecmd:
if c != nil {
if c.IsEditCmd {
println("Cedit send")
editpkg.Cedit <- 0
}
fsysdelid(c.Mntdir)
Expand Down
1 change: 0 additions & 1 deletion cmd/acme/dat.h.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ type Waitmsg struct {

var (
cplumb = make(chan *plumb.Message)
cwait = make(chan *Waitmsg)
cxfidalloc = make(chan *Xfid) // TODO bidi
cxfidfree = make(chan *Xfid)
cnewwindow = make(chan *wind.Window) // TODO bidi
Expand Down
5 changes: 5 additions & 0 deletions cmd/acme/internal/edit/ecmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ import (
"9fans.net/go/cmd/acme/internal/wind"
)

var BigLock = func() {}
var BigUnlock = func() {}

var Glooping int
var nest int
var Enoname = "no file name given"
Expand Down Expand Up @@ -549,7 +552,9 @@ func runpipe(t *wind.Text, cmd rune, cr []rune, state int) {
wind.Winunlock(t.W)
}
wind.TheRow.Lk.Unlock()
BigUnlock()
<-Cedit
BigLock()
var q *util.QLock
/*
* The editoutlk exists only so that we can tell when
Expand Down
32 changes: 21 additions & 11 deletions cmd/acme/internal/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ var Fsysmount = func([]rune, [][]rune) *base.Mntdir { return nil }
var Fsysdelid = func(*base.Mntdir) {}
var Xfidlog = func(*wind.Window, string) {}

var Cwait = make(chan Waitmsg)

type Waitmsg struct {
Proc *os.Process
Err error
}

/*
* These functions get called as:
*
Expand Down Expand Up @@ -908,7 +915,7 @@ func tab(et, _, argt *wind.Text, _, _ bool, arg []rune) {
}
}

func runproc(win *wind.Window, s string, rdir []rune, newns bool, argaddr, xarg *string, c *Command, cpid chan int, iseditcmd bool) {
func runproc(win *wind.Window, s string, rdir []rune, newns bool, argaddr, xarg *string, c *Command, cpid chan *os.Process, iseditcmd bool) {
t := strings.TrimLeft(s, " \n\t")
name := t
if i := strings.IndexAny(name, " \n\t"); i >= 0 {
Expand Down Expand Up @@ -1056,8 +1063,11 @@ func runproc(win *wind.Window, s string, rdir []rune, newns bool, argaddr, xarg
err := cmd.Start()
if err == nil {
if cpid != nil {
cpid <- cmd.Process.Pid // TODO(rsc): send cmd.Process
cpid <- cmd.Process // TODO(rsc): send cmd.Process
}
go func() {
Cwait <- Waitmsg{cmd.Process, cmd.Wait()}
}()
return
}
goto Fail
Expand Down Expand Up @@ -1086,7 +1096,7 @@ Hard:
err := cmd.Start()
if err == nil {
if cpid != nil {
cpid <- cmd.Process.Pid // TODO(rsc): send cmd.Process
cpid <- cmd.Process // TODO(rsc): send cmd.Process
}
return
}
Expand All @@ -1096,14 +1106,14 @@ Hard:

Fail:
if cpid != nil { // TODO(rsc): is it always non-nil?
cpid <- 0
cpid <- nil
}
}

func runwaittask(c *Command, cpid chan int) {
c.Pid = <-cpid
func runwaittask(c *Command, cproc chan *os.Process) {
c.Proc = <-cproc
c.av = nil
if c.Pid != 0 { // successful exec
if c.Proc != nil { // successful exec
Ccommand <- c
} else if c.IsEditCmd {
edit.Cedit <- 0
Expand All @@ -1115,10 +1125,10 @@ func Run(win *wind.Window, s string, rdir []rune, newns bool, argaddr, xarg *str
return
}
c := new(Command)
cpid := make(chan int, 0)
go runproc(win, s, rdir, newns, argaddr, xarg, c, cpid, iseditcmd)
cproc := make(chan *os.Process, 0)
go runproc(win, s, rdir, newns, argaddr, xarg, c, cproc, iseditcmd)
// mustn't block here because must be ready to answer mount() call in run()
go runwaittask(c, cpid)
go runwaittask(c, cproc)
}

func fsopenfd(fs *client.Fsys, name string, mode uint8) (*os.File, error) {
Expand Down Expand Up @@ -1148,7 +1158,7 @@ func fsopenfd(fs *client.Fsys, name string, mode uint8) (*os.File, error) {
}

type Command struct {
Pid int
Proc *os.Process
Name []rune
text string
av []string
Expand Down
2 changes: 2 additions & 0 deletions cmd/acme/internal/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ type File struct {
mod bool
}

func (f *File) SetView(v View) { f.view = v }

type View interface {
Insert(int, []rune)
Delete(int, int)
Expand Down
40 changes: 28 additions & 12 deletions cmd/acme/internal/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package util
import (
"log"
"sync/atomic"
"sync"
)

func Min(a int, b int) int {
Expand All @@ -37,28 +38,43 @@ func Fatal(s string) {
log.Fatalf("acme: %s\n", s)
}

var locks struct {
mu sync.Mutex
cond sync.Cond
}

func init() {
locks.cond.L = &locks.mu
}

type QLock struct {
held chan bool
held uint32
}

func (l *QLock) TryLock() bool {
if l.held == nil {
panic("missing held")
}
select {
case l.held <- true:
return true
default:
return false
}
return atomic.CompareAndSwapUint32(&l.held, 0, 1)
}

func (l *QLock) Unlock() {
<-l.held
v := atomic.SwapUint32(&l.held, 0)
if v == 0 {
panic("Unlock of unlocked lock")
}
if v > 1 {
locks.cond.Broadcast()
}
}

func (l *QLock) Lock() {
l.held <- true
if atomic.AddUint32(&l.held, 1) == 1 {
return
}
locks.mu.Lock()
defer locks.mu.Unlock()

for atomic.AddUint32(&l.held, 1) != 1 {
locks.cond.Wait()
}
}

func Incref(p *uint32) { atomic.AddUint32(p, 1) }
Expand Down
1 change: 1 addition & 0 deletions cmd/acme/internal/wind/text.go
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,7 @@ func ishtmlend(t *Text, q int, q0 *int) int {
func fileaddtext(f *File, t *Text) *File {
if f == nil {
f = &File{File: new(file.File)}
f.File.SetView((*fileView)(f))
f.Unread = true
}
f.Text = append(f.Text, t)
Expand Down

0 comments on commit 0b266bf

Please sign in to comment.