From e1e03e50ae5c2c1321096d56c12e1e6f573b00a9 Mon Sep 17 00:00:00 2001 From: Ollie Agent Date: Sun, 2 Aug 2026 16:18:32 +0200 Subject: [PATCH] =?UTF-8?q?Inline=20handle=20into=20Start;=20rename=20Serv?= =?UTF-8?q?e=E2=86=92Start,=20Shutdown=E2=86=92Kill?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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. --- cmd/olliesrv/main.go | 6 +++--- cmd/olliesrv/server.go | 42 ++++++++++++++++++++---------------------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/cmd/olliesrv/main.go b/cmd/olliesrv/main.go index 20b18cb..55185f5 100644 --- a/cmd/olliesrv/main.go +++ b/cmd/olliesrv/main.go @@ -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) diff --git a/cmd/olliesrv/server.go b/cmd/olliesrv/server.go index de7d113..0f6b273 100644 --- a/cmd/olliesrv/server.go +++ b/cmd/olliesrv/server.go @@ -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 {