Skip to content

Conversation

@snakefoot
Copy link
Contributor

No description provided.

@snakefoot snakefoot added the enhancement Improvement on existing feature label Sep 27, 2025
@coderabbitai
Copy link

coderabbitai bot commented Sep 27, 2025

Walkthrough

Tightens and reorders disposal and stop conditions for XmlLoggingConfiguration's auto-reload watcher: stricter check before stopping, streamlined timer disposal, and a re-entrancy-guarded Dispose that captures the timer, clears state under lock, then unsubscribes and disposes after the lock to reduce races. (49 words)

Changes

Cohort / File(s) Summary
Auto-reload watcher lifecycle & disposal
src/NLog/Config/XmlLoggingConfiguration.cs
- OnConfigurationAssigned: require watcher to be non-null and not disposed before stopping
- ReloadTimer: set field to null and dispose captured timer via null-conditional operator (remove nested disposal block)
- RefreshFileWatcher.Dispose: add re-entrancy guard, capture local reloadTimer before locking, set disposing flag and clear fields inside lock, then unsubscribe FileChanged and dispose captured timer after releasing the lock
- Remove re-subscription call to _fileWatcher.Watch from ReloadTimer catch path; minor sequencing tweaks in Dispose

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor Caller
    participant Config as XmlLoggingConfiguration
    participant Watcher as AutoReloadConfigFileWatcher
    participant FS as FileSystemWatcher
    participant Timer as ReloadTimer

    rect rgba(230,240,255,0.45)
    Caller->>Config: OnConfigurationAssigned()
    alt watcher != null && watcher not disposed
        Config->>Watcher: Stop()/Dispose()
    else
        Note right of Config: no stop/dispose
    end
    end

    rect rgba(240,255,230,0.45)
    Caller->>Watcher: Dispose()
    alt first call (not disposing)
        Watcher->>Watcher: capture localReloadTimer
        Watcher->>Watcher: lock(this)\nset _isDisposing = true\nclear fields (e.g., _reloadTimer)
        Watcher-->>FS: Unsubscribe FileChanged (after lock)
        Watcher-->>Timer: Dispose captured timer (after lock)
    else re-entrant call
        Watcher->>Watcher: return early (guard)
    end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

I twitch an ear at racing threads,
Tip-tap paws hush ticking dreads;
Capture the clock, lock the door,
Unsubscribe, then close once more.
Clean burrow, quiet timer—hop away. 🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The pull request description is empty and does not provide any information about the changes made, so it fails to meet the requirement of being at least related to the changeset. Please add a concise description summarizing the modifications to XmlLoggingConfiguration and the rationale for protecting against double disposal of AutoReloadConfigFileWatcher.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title accurately identifies the key change in XmlLoggingConfiguration by specifying protection against double disposal of AutoReloadConfigFileWatcher and is concise and directly related to the main changeset.
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 3f3b473 and 8bf7022.

📒 Files selected for processing (1)
  • src/NLog/Config/XmlLoggingConfiguration.cs (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/NLog/Config/XmlLoggingConfiguration.cs (1)
src/NLog/Internal/MultiFileWatcher.cs (1)
  • Dispose (71-75)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: task-list-completed
🔇 Additional comments (3)
src/NLog/Config/XmlLoggingConfiguration.cs (3)

259-263: Guarding against double dispose looks solid

The explicit !fileWatcher.IsDisposed check prevents us from calling into a watcher that is already tearing down, which keeps AutoReload stop/start sequences cleaner. Nicely done.


664-666: Timer cleanup sequencing is tidy

Clearing _reloadTimer under the lock before disposing the captured instance ensures future file-change events can safely spin up a fresh timer without racing against a pending dispose. 👍


718-731: Re-entrancy-safe dispose flow

Capturing the timer, marking _isDisposing inside the lock, and then performing event unsubscription/cleanup afterward closes the window for re-entrancy while still avoiding lock-held disposals. This looks robust.


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.

@snakefoot snakefoot force-pushed the dev branch 2 times, most recently from 75e7278 to 3f3b473 Compare September 27, 2025 06:46
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: 0

🧹 Nitpick comments (1)
src/NLog/Config/XmlLoggingConfiguration.cs (1)

647-650: Consider consolidating duplicate disposal checks

The _isDisposing check appears twice at the beginning of this method (lines 647 and 658). While the second check after acquiring the lock is necessary for thread safety, the first check seems redundant since the timer callback should only execute if the timer hasn't been disposed yet.

Consider removing the first check to simplify the code:

 private void ReloadTimer(object state)
 {
-    if (_isDisposing)
-    {
-        return; //timer was disposed already.
-    }
-
     LoggingConfiguration oldConfig = (LoggingConfiguration)state;

The lock-protected check on line 658 provides sufficient protection.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 66696bf and a60be25.

📒 Files selected for processing (1)
  • src/NLog/Config/XmlLoggingConfiguration.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/NLog/Config/XmlLoggingConfiguration.cs (2)
src/NLog/Internal/TimeoutContinuation.cs (1)
  • Dispose (85-88)
src/NLog/Internal/MultiFileWatcher.cs (1)
  • Dispose (71-75)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: task-list-completed
🔇 Additional comments (2)
src/NLog/Config/XmlLoggingConfiguration.cs (2)

259-259: Good defensive check against disposed watchers

The additional !fileWatcher.IsDisposed check prevents unnecessary disposal attempts on already disposed watchers. This is a solid defensive programming practice.


722-735: Well-implemented double-dispose protection with improved thread safety

The refactored Dispose method introduces several important improvements:

  1. Captures the timer reference before entering the lock to minimize lock scope
  2. Adds a re-entrancy guard with _isDisposing check to prevent double disposal
  3. Properly sequences operations: state cleanup under lock, then disposal outside the lock to avoid potential deadlocks
  4. Unsubscribes from events and disposes resources after releasing the lock

This pattern effectively prevents race conditions and ensures clean resource cleanup.

@snakefoot snakefoot closed this Sep 27, 2025
@snakefoot snakefoot reopened this Sep 27, 2025
@sonarqubecloud
Copy link

@snakefoot snakefoot merged commit fe0bb0b into NLog:dev Sep 27, 2025
5 of 6 checks passed
@snakefoot snakefoot added this to the 6.0.5 milestone Sep 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Improvement on existing feature size/S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant