Inline handle into Start; rename Serve→Start, Shutdown→Kill

- handle() is gone — the dispatch + panic recovery is inlined into
  the per-request goroutine in Start(). Panic recovery is lifecycle,
  not protocol handling.
- Serve → Start: accepts a connection and runs the 9P loop
- Shutdown → Kill: stops accepting, cancels sessions, waits for
  goroutines to drain.
- 2 methods remain on *Server: Start, Kill. Server is purely lifecycle.
- All 9P protocol handlers are package-level functions.
This commit is contained in:
Ollie Agent 2026-08-02 16:18:32 +02:00
parent 447156ce13
commit e1e03e50ae
2 changed files with 23 additions and 25 deletions

View File

@ -214,7 +214,7 @@ func runServer(sockPath string) {
if err != nil {
return
}
go srv.Serve(conn)
go srv.Start(conn)
}
}()
@ -235,7 +235,7 @@ func runServer(sockPath string) {
if err != nil {
return
}
go srv.Serve(conn)
go srv.Start(conn)
}
}()
fmt.Printf("olliesrv listening on tcp %s\n", *tcpAddr)
@ -257,7 +257,7 @@ func runServer(sockPath string) {
daemonCancel() // signal all sessions via context propagation
if srv != nil {
srv.Shutdown()
srv.Kill()
}
if true {
os.Remove(sockPath)

View File

@ -125,7 +125,7 @@ func New(cfg Config) *Server {
},
plan9.Tauth: func(cs *connState, fc *plan9.Fcall, _ context.Context) *plan9.Fcall { return errFcall(fc, "no auth required") },
plan9.Tflush: func(cs *connState, fc *plan9.Fcall, _ context.Context) *plan9.Fcall { return flush(cs, fc) },
plan9.Tattach: func(cs *connState, fc *plan9.Fcall, _ context.Context) *plan9.Fcall { return attach(s.sink.Logger("9p", olog.LevelDebug), s.groups, cs, fc) },
plan9.Tattach: func(cs *connState, fc *plan9.Fcall, _ context.Context) *plan9.Fcall { return attach(s.groups, cs, fc) },
plan9.Twalk: func(cs *connState, fc *plan9.Fcall, _ context.Context) *plan9.Fcall { return walk(cfg.RootTree, cs, fc) },
plan9.Topen: func(cs *connState, fc *plan9.Fcall, _ context.Context) *plan9.Fcall { return open(cfg.RootTree, s.groups, cs, fc) },
plan9.Tcreate: func(cs *connState, fc *plan9.Fcall, _ context.Context) *plan9.Fcall { return create(cfg.RootTree, cs, fc) },
@ -163,7 +163,7 @@ func hasPermBits(mode uint8, bits uint32) bool {
const readTimeout = 10 * time.Second
func (s *Server) Serve(conn net.Conn) {
func (s *Server) Start(conn net.Conn) {
defer conn.Close()
s.serveWG.Add(1)
defer s.serveWG.Done()
@ -222,6 +222,21 @@ func (s *Server) Serve(conn net.Conn) {
wg.Add(1)
go func(fc *plan9.Fcall, ctx context.Context) {
start := time.Now()
resp := func() (r *plan9.Fcall) {
defer func() {
if rec := recover(); rec != nil {
s.log.Error("panic in handle: %v", rec)
r = errFcall(fc, "internal error")
}
s.log.Debug(" -> %s %dµs", fcallTypeName(fc.Type), time.Since(start).Microseconds())
}()
h := s.handler[fc.Type]
if h == nil {
return errFcall(fc, "unsupported operation")
}
return h(cs, fc, ctx)
}()
defer func() {
reqCancel()
cs.mu.Lock()
@ -229,29 +244,13 @@ func (s *Server) Serve(conn net.Conn) {
cs.mu.Unlock()
wg.Done()
}()
responses <- s.handle(cs, fc, ctx)
responses <- resp
}(fc, reqCtx)
}
wg.Wait()
close(responses)
}
func (s *Server) handle(cs *connState, fc *plan9.Fcall, ctx context.Context) (resp *plan9.Fcall) {
start := time.Now()
defer func() {
if r := recover(); r != nil {
s.log.Error("panic in handle: %v", r)
resp = errFcall(fc, "internal error")
}
s.log.Debug(" -> %s %dµs", fcallTypeName(fc.Type), time.Since(start).Microseconds())
}()
h := s.handler[fc.Type]
if h == nil {
return errFcall(fc, "unsupported operation")
}
return h(cs, fc, ctx)
}
func flush(cs *connState, fc *plan9.Fcall) *plan9.Fcall {
cs.mu.Lock()
if cancel, ok := cs.pending[fc.Oldtag]; ok {
@ -333,7 +332,7 @@ func pathBase(path string) string {
return path[i+1:]
}
func attach(log *olog.Logger, groups *GroupTable, cs *connState, fc *plan9.Fcall) *plan9.Fcall {
func attach(groups *GroupTable, cs *connState, fc *plan9.Fcall) *plan9.Fcall {
cs.mu.Lock()
defer cs.mu.Unlock()
if _, exists := cs.fids[fc.Fid]; exists {
@ -342,7 +341,6 @@ func attach(log *olog.Logger, groups *GroupTable, cs *connState, fc *plan9.Fcall
cs.uname = fc.Uname
qid := plan9.Qid{Type: QTDir, Path: 0}
cs.fids[fc.Fid] = &fid{path: "/", qid: qid}
log.Debug("Tattach uname=%q", fc.Uname)
if fc.Uname != "" {
groups.Add("agent", fc.Uname)
}
@ -687,7 +685,7 @@ func remove(root *fs.Tree, cs *connState, fc *plan9.Fcall) *plan9.Fcall {
return &plan9.Fcall{Type: plan9.Rremove, Tag: fc.Tag}
}
func (s *Server) Shutdown() {
func (s *Server) Kill() {
s.shutdownCancel()
s.connMu.Lock()
for conn := range s.activeConns {