Skip to content

Comments

fix(breakhandler): synchronize login lifecycle#1572

Closed
chsami wants to merge 1 commit intodevelopmentfrom
codex/fix-breakhandler-login/logout-loop
Closed

fix(breakhandler): synchronize login lifecycle#1572
chsami wants to merge 1 commit intodevelopmentfrom
codex/fix-breakhandler-login/logout-loop

Conversation

@chsami
Copy link
Owner

@chsami chsami commented Oct 16, 2025

Summary

  • guard BreakHandler startup with a controller flag and state lock to prevent duplicate schedulers
  • serialize logout/login paths with a shared lock and defensive state checks to avoid desynchronization
  • update AutoLogin to respect the BreakHandler login lock before issuing retry attempts

Testing

  • mvn -pl runelite-client -am -DskipTests compile (fails: unable to download com.google.inject:guice-bom:4.1.0 due to 403 Forbidden)

https://chatgpt.com/codex/tasks/task_e_68f11da370588328be530d0bdc1a7782

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 16, 2025

Walkthrough

This pull request adds concurrency control mechanisms to prevent overlapping login attempts across the AutoLoginScript and BreakHandlerScript. AutoLoginScript now acquires a login lock at the start of initiateLogin() and releases it in a finally block, skipping attempts if the lock cannot be acquired. BreakHandlerScript introduces stateLock and loginSequenceLock ReentrantLock instances along with new public API methods (tryAcquireLoginLock(), releaseLoginLock()) to coordinate execution and serialize login/logout sequences. State transitions are now guarded by locks to ensure thread-safe state management.

Possibly related PRs

  • fix: prevent multiple Login instances in break handler #1524: Both PRs modify BreakHandlerScript's login sequencing to serialize and prevent concurrent login attempts, with the retrieved PR transitioning state to LOGGING_IN while this PR adds explicit lock-based serialization.

  • autologin region filters #1448: Both PRs modify AutoLoginScript and BreakHandlerScript's login-guarding behavior to coordinate auto-login flow and prevent duplicate login attempts.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 63.64% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title "fix(breakhandler): synchronize login lifecycle" is specific and clearly aligned with the primary changes in the pull request. It directly addresses the main objective of implementing synchronization mechanisms to serialize login and logout flows, which is the central theme across both modified files (BreakHandlerScript adding locks and state synchronization, AutoLoginScript respecting the BreakHandler login lock). The title uses conventional commit format and is concise while conveying the essential change without being overly broad or vague.
Description Check ✅ Passed The pull request description is directly related to the changeset and provides meaningful details about the changes. It explicitly mentions guarding BreakHandler startup with a controller flag and state lock, serializing logout/login paths with a shared lock, and updating AutoLogin to respect the BreakHandler login lock—all of which align with the modifications shown in the raw summary. The description is specific and informative rather than vague or generic, making it clear what was changed and why.
✨ Finishing touches
  • 📝 Generate docstrings

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
Contributor

@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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 34ddf36 and da0b7cd.

📒 Files selected for processing (2)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/accountselector/AutoLoginScript.java (4 hunks)
  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java (8 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-25T07:26:53.623Z
Learnt from: Voxsylvae
PR: chsami/Microbot#1415
File: runelite-client/src/main/java/net/runelite/client/plugins/microbot/pluginscheduler/SchedulerPlugin.java:2341-2366
Timestamp: 2025-08-25T07:26:53.623Z
Learning: In SchedulerPlugin.startLoginMonitoringThread(), do not gate startup on isBreakHandlerEnabled(); rely on isOnBreak() to suppress the monitor only when a break is actually active. This avoids blocking login monitoring whenever BreakHandler is merely enabled.

Applied to files:

  • runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java
🧬 Code graph analysis (2)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/accountselector/AutoLoginScript.java (1)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/player/Rs2Player.java (1)
  • Rs2Player (52-1795)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java (1)
runelite-client/src/main/java/net/runelite/client/plugins/microbot/util/player/Rs2Player.java (1)
  • Rs2Player (52-1795)
⏰ 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). (2)
  • GitHub Check: Build
  • GitHub Check: Build

Comment on lines 755 to 766
BreakHandlerState oldState = currentState.get();
if (oldState != newState) {
log.debug("State transition: {} -> {}", oldState, newState);
currentState.set(newState);
stateChangeTime.set(Instant.now());
retryCount.set(0);

// Reset safe condition wait time when leaving BREAK_REQUESTED
if (newState != BreakHandlerState.BREAK_REQUESTED) {
safeConditionWaitStartTime = null;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Preserve the login retry counter between LOGIN_REQUESTED ↔ LOGGING_IN hops

Resetting retryCount inside transitionToStateInternal now fires every time we bounce between LOGGING_IN and LOGIN_REQUESTED. As a result handleLoggingInState always reads currentRetryCount == 0, the "retry N of max" log never increments past 1, and we never hit getMaxLoginRetries(). That turns the login limiter into a no-op and lets us hammer the login flow indefinitely. Keep the counter when shuttling between those two states (reset everywhere else) so the retry guard can actually trip.

-            retryCount.set(0);
+            if (!((oldState == BreakHandlerState.LOGGING_IN && newState == BreakHandlerState.LOGIN_REQUESTED)
+                || (oldState == BreakHandlerState.LOGIN_REQUESTED && newState == BreakHandlerState.LOGGING_IN))) {
+                retryCount.set(0);
+            }
📝 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
BreakHandlerState oldState = currentState.get();
if (oldState != newState) {
log.debug("State transition: {} -> {}", oldState, newState);
currentState.set(newState);
stateChangeTime.set(Instant.now());
retryCount.set(0);
// Reset safe condition wait time when leaving BREAK_REQUESTED
if (newState != BreakHandlerState.BREAK_REQUESTED) {
safeConditionWaitStartTime = null;
}
}
BreakHandlerState oldState = currentState.get();
if (oldState != newState) {
log.debug("State transition: {} -> {}", oldState, newState);
currentState.set(newState);
stateChangeTime.set(Instant.now());
if (!((oldState == BreakHandlerState.LOGGING_IN && newState == BreakHandlerState.LOGIN_REQUESTED)
|| (oldState == BreakHandlerState.LOGIN_REQUESTED && newState == BreakHandlerState.LOGGING_IN))) {
retryCount.set(0);
}
// Reset safe condition wait time when leaving BREAK_REQUESTED
if (newState != BreakHandlerState.BREAK_REQUESTED) {
safeConditionWaitStartTime = null;
}
}
🤖 Prompt for AI Agents
In
runelite-client/src/main/java/net/runelite/client/plugins/microbot/breakhandler/BreakHandlerScript.java
around lines 755 to 766, the code unconditionally resets retryCount on every
state transition which wipes the login retry counter when bouncing between
LOGIN_REQUESTED and LOGGING_IN; change the reset logic so retryCount is NOT
reset when transitioning between LOGIN_REQUESTED and LOGGING_IN in either
direction, but is still reset for all other state transitions (keep existing
resets of stateChangeTime and safeConditionWaitStartTime behavior unchanged).

@chsami chsami closed this Oct 16, 2025
@chsami chsami deleted the codex/fix-breakhandler-login/logout-loop branch November 16, 2025 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant