Skip to content

Comments

fix: fix issue detect by doubao#94

Open
Wangzy455 wants to merge 5 commits intoAlexStocks:masterfrom
Wangzy455:fix/doubao
Open

fix: fix issue detect by doubao#94
Wangzy455 wants to merge 5 commits intoAlexStocks:masterfrom
Wangzy455:fix/doubao

Conversation

@Wangzy455
Copy link

@Wangzy455 Wangzy455 commented Sep 21, 2025

What this PR does:
fix issue93

Which issue(s) this PR fixes:

for #93

Special notes for your reviewer:
NONE

Does this PR introduce a user-facing change?:
NONE

Summary by CodeRabbit

  • Bug Fixes

    • Reduced spurious error output during shutdown and connection closure.
    • Added session close coordination to ensure cleaner, reliable teardowns.
  • Refactor

    • Logging API now returns errors; internal logging adapter and callers updated.
  • Stability

    • Suppressed noisy logging side-effects to avoid misleading error traces during normal operation.

@coderabbitai
Copy link

coderabbitai bot commented Sep 22, 2025

Walkthrough

Logger.Error/Errorf now return error and a zap adapter was added; many logging call sites were updated to explicitly discard the returned error (assign to _). Session gained a closeWait channel and an early Close guard; server shutdown/serve error paths now discard returned errors. Only Logger interface signatures were exportedly changed.

Changes

Cohort / File(s) Summary of Changes
Logger API & adapter
util/logger.go
Logger.Error and Logger.Errorf signatures changed to return error; added zapLoggerAdapter to wrap zap.SugaredLogger; global log init and public Error/Errorf functions updated to return/propagate adapter errors.
Transport: logging-result discard
transport/callback.go, transport/connection.go, transport/server.go, transport/tls.go
Replaced prior ignored log.Error/log.Errorf calls with explicit discards (_ = log.Error(...) / _ = log.Errorf(...)) across multiple error paths (callback add/remove, connection CloseConn/snappy close, server shutdown/serve, TLS build errors). No control-flow changes besides swallowing the logger-returned error.
Session sync & guards
transport/session.go
Added closeWait chan struct{} to session and initialize it; close closeWait when handler goroutine count (grNum) hits zero; added early-return guard in Close() if already closed; updated some panic/error logging calls to discard returned errors.
Examples: echo handlers/readwriters
examples/echo/tcp-echo/server/..., examples/echo/tcp-echo/client/...
Updated various example code logging calls to assign logging returns to _ (e.g., EchoPackage.Unmarshal, handlers, readwriter). Behavior unchanged aside from explicit discard of logger return values.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client
  participant Session
  participant Handler
  participant closeWait as closeWait (chan)

  Note over Session: Session now owns `closeWait`

  Client->>Session: start handler (increment grNum)
  Session->>Handler: run handler goroutine
  Handler-->>Session: handler done (decrement grNum)
  alt grNum > 0
    Note right of Session: other handlers still running
  else grNum == 0
    Session->>closeWait: close(closeWait)
    Note right of closeWait: handlers drained — signal released
  end

  Client->>Session: Close()
  Session->>Session: if IsClosed() return early
  Note over Session: Close may wait on `closeWait` before final cleanup
  Note over Session: logging calls now use `_ = log.Error(...)` to discard adapter errors
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • AlexStocks

Poem

A rabbit hops through lines of code,
I hush the logger's tiny cry.
A channel waits until it's closed,
Goroutines finish — then goodbye.
Blank IDs tuck errors away, so quiet I spy. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title Check ⚠️ Warning The title “fix: fix issue detect by doubao” does not clearly summarize the substantive change but merely indicates an unspecified fix referencing the reporter, offering no insight into what was altered or improved in the codebase. Rename the title to concisely describe the main code change (for example “logger: discard unused return values to silence error warnings”) and remove the reference to the issue reporter.
Linked Issues Check ⚠️ Warning Although the changes standardize logging calls and introduce a session close notification channel, they only address a subset of the linked issue’s objectives around logging and goroutine coordination. The pull request does not implement atomic safety for session counters, RPC boundary markers, front-end XSS sanitization, dependency cleanup, Go version constraints, template improvements, or error feedback for one-way RPC calls. Implement the remaining objectives or decompose the work into focused pull requests that each fully address a specific set of issues documented in #93.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Out of Scope Changes Check ✅ Passed All modifications in this pull request relate directly to enhancing logging behavior and managing session shutdown signaling, which correspond to the logging and concurrency objectives in the linked issue. There are no detected changes unrelated to those scopes.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6974818 and f61e2cb.

📒 Files selected for processing (6)
  • examples/echo/tcp-echo/client/app/echo.go (1 hunks)
  • examples/echo/tcp-echo/client/app/handler.go (2 hunks)
  • examples/echo/tcp-echo/client/app/readwriter.go (1 hunks)
  • examples/echo/tcp-echo/server/app/echo.go (1 hunks)
  • examples/echo/tcp-echo/server/app/handler.go (1 hunks)
  • examples/echo/tcp-echo/server/app/readwriter.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
examples/echo/tcp-echo/client/app/handler.go (2)
util/logger.go (1)
  • Error (181-183)
examples/echo/ws-echo/client/app/handler.go (2)
  • h (66-75)
  • h (77-89)
examples/echo/tcp-echo/client/app/echo.go (1)
util/logger.go (1)
  • Error (181-183)
examples/echo/tcp-echo/server/app/readwriter.go (1)
util/logger.go (1)
  • Error (181-183)
examples/echo/tcp-echo/server/app/handler.go (1)
util/logger.go (1)
  • Error (181-183)
examples/echo/tcp-echo/client/app/readwriter.go (1)
util/logger.go (1)
  • Error (181-183)
examples/echo/tcp-echo/server/app/echo.go (1)
util/logger.go (1)
  • Error (181-183)
🔇 Additional comments (6)
examples/echo/tcp-echo/server/app/echo.go (1)

135-135: Logging error return safely discarded

Assigning the result to _ keeps the log side effect while appeasing the new error-returning signature—looks good.

examples/echo/tcp-echo/client/app/echo.go (1)

135-135: Consistent handling of Logger.Error return

This mirrors the updated logging API contract without altering behavior—no further changes needed.

examples/echo/tcp-echo/client/app/handler.go (1)

69-81: Good: Logger.Error results consistently ignored

Both call sites now discard the returned error explicitly, matching the revised logger interface while preserving control flow.

examples/echo/tcp-echo/client/app/readwriter.go (1)

71-71: Acknowledged: no-op assignment for log.Error

The blank identifier keeps the log call and satisfies the new signature—LGTM.

examples/echo/tcp-echo/server/app/readwriter.go (1)

71-71: Logging change aligns with new signature

Capturing the return value with _ avoids unused-result noise while keeping the log; all good here.

examples/echo/tcp-echo/server/app/handler.go (1)

136-143: Discarding the logging error is fine here.

log.Error now surfaces an error, and explicitly assigning to _ keeps the original control flow intact without triggering unused-result warnings. No further action needed.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (7)
transport/connection.go (1)

340-345: Also close flate writer to flush trailing bytes.

We only close the snappy writer. If SetCompressType selected flate, writeFlusher.flusher.Close() should be called to flush and free resources.

Apply this diff:

 if t.conn != nil {
     if writer, ok := t.writer.(*snappy.Writer); ok {
         if err := writer.Close(); err != nil {
             _ = log.Errorf("snappy.Writer.Close() = error:%+v", err)
         }
+    } else if wf, ok := t.writer.(*writeFlusher); ok && wf.flusher != nil {
+        if err := wf.flusher.Close(); err != nil {
+            _ = log.Errorf("flate.Writer.Close() = error:%+v", err)
+        }
     }
transport/callback.go (2)

72-76: Logging style nit: avoid constructing an error just to log.

Prefer formatting directly via Errorf to skip an allocation.

-        _ = log.Error(perrors.New(fmt.Sprintf("callbacks.Add: non-comparable handler/key: %T, %T; ignored", handler, key)))
+        _ = log.Errorf("callbacks.Add: non-comparable handler/key: %T, %T; ignored", handler, key)

110-114: Same here for Remove().

Mirror the style from Add().

-        _ = log.Error(perrors.New(fmt.Sprintf("callbacks.Remove: non-comparable handler/key: %T, %T; ignored", handler, key)))
+        _ = log.Errorf("callbacks.Remove: non-comparable handler/key: %T, %T; ignored", handler, key)
transport/server.go (1)

425-428: Don’t log expected http.ErrServerClosed on normal shutdown.

Serve returns http.ErrServerClosed after Shutdown. Filter it to reduce noise.

-        err = server.Serve(s.streamListener)
-        if err != nil {
-            _ = log.Errorf("http.server.Serve(addr{%s}) = err:%+v", s.addr, perrors.WithStack(err))
-        }
+        if err = server.Serve(s.streamListener); err != nil && !errors.Is(err, http.ErrServerClosed) {
+            _ = log.Errorf("http.server.Serve(addr{%s}) = err:%+v", s.addr, perrors.WithStack(err))
+        }

Add import:

 import (
     "context"
     "crypto/tls"
     "crypto/x509"
     "fmt"
     "net"
     "net/http"
     "os"
     "strings"
     "sync"
     "time"
+    "errors"
 )
transport/session.go (2)

610-612: Close closeWait only when non-nil (belt-and-suspenders).

Even after fixing Reset(), guarding the close is safer during refactors.

-        if grNum == 0 {
-            close(s.closeWait)
-        }
+        if grNum == 0 && s.closeWait != nil {
+            close(s.closeWait)
+        }

145-148: Expose a wait helper to make closeWait useful.

Optional: add WaitClosed(ctx) so callers can block until goroutines drain.

Add method:

// WaitClosed blocks until the session’s worker goroutine exits or ctx times out.
func (s *session) WaitClosed(ctx context.Context) error {
    if s == nil {
        return nil
    }
    select {
    case <-s.closeWait:
        return nil
    case <-ctx.Done():
        return ctx.Err()
    }
}

Would you like me to wire this into callers (e.g., server shutdown) if present?

util/logger.go (1)

181-188: Harden Error/Errorf against panics from custom loggers.

Guard these wrappers with recover() so logging can’t crash the process (one of the doubao findings).

-// Error
-func Error(args ...any) error {
-    return log.Error(args...)
-}
+// Error
+func Error(args ...any) (err error) {
+    defer func() {
+        if r := recover(); r != nil {
+            err = fmt.Errorf("logger panic: %v", r)
+        }
+    }()
+    return log.Error(args...)
+}
 
-// Errorf
-func Errorf(template string, args ...any) error {
-    return log.Errorf(template, args...)
-}
+// Errorf
+func Errorf(template string, args ...any) (err error) {
+    defer func() {
+        if r := recover(); r != nil {
+            err = fmt.Errorf("logger panic: %v", r)
+        }
+    }()
+    return log.Errorf(template, args...)
+}

Add import:

 import (
     "go.uber.org/zap"
     "go.uber.org/zap/zapcore"
+    "fmt"
 )
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a282367 and eb0c902.

📒 Files selected for processing (5)
  • transport/callback.go (2 hunks)
  • transport/connection.go (1 hunks)
  • transport/server.go (2 hunks)
  • transport/session.go (5 hunks)
  • util/logger.go (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
transport/connection.go (1)
util/logger.go (1)
  • Errorf (186-188)
transport/callback.go (1)
util/logger.go (1)
  • Error (181-183)
transport/server.go (1)
util/logger.go (1)
  • Errorf (186-188)
transport/session.go (1)
util/logger.go (1)
  • Error (181-183)
🔇 Additional comments (5)
transport/connection.go (1)

343-343: No-op assignment is fine; close error is logged.

Using _ = log.Errorf(...) is consistent with the new logger signature and keeps behavior unchanged.

transport/server.go (1)

156-160: OK to discard logging error; consider severity.

Keeping the error log on shutdown failure is good. No functional change introduced here.

transport/session.go (2)

401-401: Discarding the logger’s returned error is fine.

The panic path is preserved; logging remains non-blocking.


924-926: Early return in Close() avoids redundant work.

Good small guard; stop() remains idempotent via once.Do anyway.

util/logger.go (1)

37-50: Adapter approach looks good.

Embedding SugaredLogger plus explicit Error/Errorf satisfies the interface cleanly.

Also applies to: 97-98, 132-133, 146-147

Comment on lines +145 to 148

// wait
closeWait chan struct{}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

New closeWait channel isn’t reinitialized in Reset(); close(nil) panic risk.

handlePackage closes s.closeWait. After Reset(), closeWait becomes nil (zero value) and closing it will panic.

Apply this diff to Reset():

 func (s *session) Reset() {
     *s = session{
         name:   defaultSessionName,
         once:   &sync.Once{},
         done:   make(chan struct{}),
         period: period,
         wait:   pendingDuration,
-        attrs:  gxcontext.NewValuesContext(context.Background()),
+        attrs:  gxcontext.NewValuesContext(context.Background()),
+        closeWait: make(chan struct{}),
     }
 }

Also applies to: 161-166

🤖 Prompt for AI Agents
In transport/session.go around lines 145-148 and also touching Reset() around
161-166, the closeWait channel is left nil after Reset(), causing a panic when
handlePackage later calls close(s.closeWait); modify Reset() to reinitialize the
channel (e.g. assign a new non-nil channel to s.closeWait) and update any close
calls to guard against nil (or use a safe close pattern such as checking for
non-nil or using sync.Once) so closing cannot panic after a Reset().

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good advice

Comment on lines +29 to 35
Error(args ...any) error
Debug(args ...any)
Infof(fmt string, args ...any)
Warnf(fmt string, args ...any)
Errorf(fmt string, args ...any)
Errorf(fmt string, args ...any) error
Debugf(fmt string, args ...any)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

🧩 Analysis chain

Breaking change: Logger.Error/Errorf now return error. Provide a backward‑compat shim.

This breaks existing custom loggers passed via SetLogger. Add a LegacyLogger adapter to preserve compatibility.

Proposed additions (outside the hunks):

// LegacyLogger mirrors the old contract (no error returns).
type LegacyLogger interface {
    Info(args ...any)
    Warn(args ...any)
    Error(args ...any)
    Debug(args ...any)
    Infof(string, ...any)
    Warnf(string, ...any)
    Errorf(string, ...any)
    Debugf(string, ...any)
}

// Wrap a legacy logger so it satisfies the new Logger.
type legacyLoggerAdapter struct{ LegacyLogger }

func (l legacyLoggerAdapter) Error(args ...any) error  { l.LegacyLogger.Error(args...); return nil }
func (l legacyLoggerAdapter) Errorf(f string, a ...any) error {
    l.LegacyLogger.Errorf(f, a...); return nil
}

// SetLegacyLogger allows existing integrations to continue working.
func SetLegacyLogger(legacy LegacyLogger) { log = legacyLoggerAdapter{LegacyLogger: legacy} }

Search for external uses in this repo:


🏁 Script executed:

#!/bin/bash
rg -nP '\bSetLogger\(' -C2

Length of output: 183


Add LegacyLogger adapter for backward compatibility
Logger.Error and Errorf now return an error, which will break any existing custom loggers passed via SetLogger. Define a LegacyLogger interface and a legacyLoggerAdapter plus SetLegacyLogger shim to preserve the old (no-error) contract:

// LegacyLogger mirrors the old contract (no error returns).
type LegacyLogger interface {
    Info(args ...any)
    Warn(args ...any)
    Error(args ...any)
    Debug(args ...any)
    Infof(string, ...any)
    Warnf(string, ...any)
    Errorf(string, ...any)
    Debugf(string, ...any)
}

// legacyLoggerAdapter wraps a LegacyLogger to satisfy the new Logger.
type legacyLoggerAdapter struct{ LegacyLogger }

func (l legacyLoggerAdapter) Error(args ...any) error {
    l.LegacyLogger.Error(args...)
    return nil
}
func (l legacyLoggerAdapter) Errorf(f string, a ...any) error {
    l.LegacyLogger.Errorf(f, a...)
    return nil
}

// SetLegacyLogger installs a LegacyLogger for compatibility with SetLogger.
func SetLegacyLogger(legacy LegacyLogger) {
    log = legacyLoggerAdapter{LegacyLogger: legacy}
}
🤖 Prompt for AI Agents
In util/logger.go around lines 29 to 35, add a LegacyLogger interface mirroring
the old no-error methods and implement a legacyLoggerAdapter that wraps a
LegacyLogger and implements the new Logger by delegating calls and returning nil
for Error and Errorf; then add a SetLegacyLogger(legacy LegacyLogger) shim that
assigns log = legacyLoggerAdapter{LegacyLogger: legacy} so existing custom
loggers continue to work without modifying their signatures.

@AlexStocks
Copy link
Owner

the ci failed. what a pity.

@Wangzy455 Wangzy455 changed the title fix: fix issue detect bu doubao fix: fix issue detect by doubao Sep 23, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3f94800 and 6974818.

📒 Files selected for processing (2)
  • transport/session.go (13 hunks)
  • transport/tls.go (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • transport/session.go
🧰 Additional context used
🧬 Code graph analysis (1)
transport/tls.go (1)
util/logger.go (2)
  • Error (181-183)
  • Errorf (186-188)

Comment on lines 75 to 78
if ok := certPool.AppendCertsFromPEM(certPem); !ok {
log.Error("failed to parse root certificate file")
_ = log.Error("failed to parse root certificate file")
return nil, err
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix returning nil error on server cert parse failure

When AppendCertsFromPEM fails, err is still nil, so we return (nil, nil) and callers treat the TLS build as successful until they dereference a nil config. Please create and propagate a real error before returning.

-		if ok := certPool.AppendCertsFromPEM(certPem); !ok {
-			_ = log.Error("failed to parse root certificate file")
-			return nil, err
+		if ok := certPool.AppendCertsFromPEM(certPem); !ok {
+			err = perrors.New("failed to parse root certificate file")
+			_ = log.Error(err)
+			return nil, err
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if ok := certPool.AppendCertsFromPEM(certPem); !ok {
log.Error("failed to parse root certificate file")
_ = log.Error("failed to parse root certificate file")
return nil, err
}
if ok := certPool.AppendCertsFromPEM(certPem); !ok {
err = perrors.New("failed to parse root certificate file")
_ = log.Error(err)
return nil, err
}
🤖 Prompt for AI Agents
In transport/tls.go around lines 75 to 78, the code logs a failure from
certPool.AppendCertsFromPEM but returns the nil err variable, causing callers to
receive (nil, nil); create a real error (e.g., fmt.Errorf or errors.New)
describing the root certificate parse failure, log that error, and return (nil,
err) so the caller receives a non-nil error indicating TLS config construction
failed.

Comment on lines 108 to 111
if !ok {
log.Error("failed to parse root certificate")
_ = log.Error("failed to parse root certificate")
return nil, err
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Propagate a real error when client cert parsing fails

Same issue here: err is nil when AppendCertsFromPEM returns false, so the function hands back (nil, nil) and masks the failure. Please instantiate and return a proper error.

-	ok := clientCertPool.AppendCertsFromPEM(certBytes)
-	if !ok {
-		_ = log.Error("failed to parse root certificate")
-		return nil, err
+	ok := clientCertPool.AppendCertsFromPEM(certBytes)
+	if !ok {
+		err = perrors.New("failed to parse root certificate")
+		_ = log.Error(err)
+		return nil, err
🤖 Prompt for AI Agents
In transport/tls.go around lines 108 to 111, when AppendCertsFromPEM returns
false the code currently logs an error but returns (nil, err) where err is nil,
causing a masked success; change this to create a real error (e.g. using
fmt.Errorf or errors.New with a clear message like "failed to parse root
certificate: AppendCertsFromPEM returned false"), log that error if desired, and
return (nil, thatError) so the caller receives a non-nil error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants