Skip to content

Restore the interrupt status in UrlChecker.waitUntilUnavailable#17719

Open
vasiliy-mikhailov wants to merge 1 commit into
SeleniumHQ:trunkfrom
vasiliy-mikhailov:fix/urlchecker-restore-interrupt
Open

Restore the interrupt status in UrlChecker.waitUntilUnavailable#17719
vasiliy-mikhailov wants to merge 1 commit into
SeleniumHQ:trunkfrom
vasiliy-mikhailov:fix/urlchecker-restore-interrupt

Conversation

@vasiliy-mikhailov

@vasiliy-mikhailov vasiliy-mikhailov commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

UrlChecker.waitUntilUnavailable catches InterruptedException and rethrows it wrapped in a RuntimeException without re-setting the thread's interrupt flag, so a caller can no longer tell the wait was interrupted. The sibling waitUntilAvailable already restores the flag in the same place, so this just makes the two consistent.

The added test interrupts the calling thread while waitUntilUnavailable is waiting and asserts the interrupt status is preserved.

AI assistance disclosure

This contribution was produced with the help of an AI pipeline. The pipeline processed a large amount of source code to surface suspected bugs, reproduced a subset of them with failing unit tests and generated candidate fixes, and prepared pull requests from the ones that held up. Each PR was then reviewed and verified by a human before being opened: the fix and test were checked by hand and the test was confirmed to fail before the change and pass after.

waitUntilUnavailable caught InterruptedException and rethrew it wrapped in a
RuntimeException without re-setting the thread interrupt flag, unlike the
sibling waitUntilAvailable. Re-set the flag so callers can still observe the
interruption.
@selenium-ci selenium-ci added the C-java Java Bindings label Jun 26, 2026
@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Restore interrupt status in UrlChecker.waitUntilUnavailable
🐞 Bug fix 🧪 Tests 🕐 10-20 Minutes

Grey Divider

Description

• Preserve thread interrupt status when waitUntilUnavailable is interrupted.
• Align interruption handling with existing waitUntilAvailable behavior.
• Add regression test asserting interrupt flag remains set after interruption.
Diagram

graph TD
A["Caller thread (test)"] --> B["UrlChecker.waitUntilUnavailable"] --> C["Wait on Future.get"] --> D{"Interrupted?"}
D -->|"yes"| E["Re-interrupt current thread"] --> F["Throw RuntimeException"]
D -->|"no"| G["Handle ExecutionException/timeout"] --> F
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Propagate InterruptedException (checked) instead of wrapping
  • ➕ Makes interruption explicit to callers via the type system
  • ➕ Avoids RuntimeException-based control flow
  • ➖ Requires API signature change and downstream call-site updates
  • ➖ Inconsistent with existing sibling method behavior if it keeps wrapping
2. Wrap in a dedicated UncheckedInterruptedException
  • ➕ Preserves interrupt semantics while communicating intent more clearly than RuntimeException
  • ➕ Can be handled distinctly from other runtime failures
  • ➖ Introduces a new exception type/API surface
  • ➖ Still requires caller awareness and documentation

Recommendation: The chosen approach (re-interrupt then wrap) is appropriate because it preserves interruption semantics without changing the public API, and it matches waitUntilAvailable’s established behavior. The main alternative—throwing InterruptedException—would be cleaner but is a breaking change.

Files changed (2) +33 / -1

Bug fix (1) +4 / -1
UrlChecker.javaRe-interrupt thread when waitUntilUnavailable is interrupted +4/-1

Re-interrupt thread when waitUntilUnavailable is interrupted

• Splits the multi-catch so InterruptedException is handled separately. Restores the current thread's interrupt flag before rethrowing as a RuntimeException, keeping behavior consistent with waitUntilAvailable.

java/src/org/openqa/selenium/net/UrlChecker.java

Tests (1) +29 / -0
UrlCheckerTest.javaAdd regression test for interrupt preservation in waitUntilUnavailable +29/-0

Add regression test for interrupt preservation in waitUntilUnavailable

• Adds a test that interrupts the calling thread while waitUntilUnavailable is blocked. Asserts a RuntimeException is thrown and the thread interrupt status remains set (then clears it to avoid leaking state).

java/test/org/openqa/selenium/net/UrlCheckerTest.java

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (1) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 18 rules

Grey Divider


Action required

1. waitUntilUnavailable missing Javadoc 📘 Rule violation ✧ Quality
Description
The modified public method waitUntilUnavailable(long timeout, TimeUnit unit, URL url) has no
Javadoc block, so its parameters and TimeoutException contract are undocumented. This violates the
requirement for complete Javadoc on changed public API methods.
Code

java/src/org/openqa/selenium/net/UrlChecker.java[R157-161]

+    } catch (InterruptedException e) {
+      Thread.currentThread().interrupt();
+      throw new RuntimeException(e);
+    } catch (ExecutionException e) {
      throw new RuntimeException(e);
Evidence
PR Compliance ID 330201 requires that every changed public method in non-test code have a Javadoc
block with descriptive text and complete tags. In UrlChecker, the public method
waitUntilUnavailable(...) has no /** ... */ comment immediately above its declaration, and the
method body was modified in this PR (catch handling), making it in-scope.

Rule 330201: Require complete Javadoc on public API methods
java/src/org/openqa/selenium/net/UrlChecker.java[108-114]
java/src/org/openqa/selenium/net/UrlChecker.java[151-162]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A changed public method `waitUntilUnavailable(...)` lacks a Javadoc block and therefore does not document purpose, `@param` tags, or the `@throws` contract.

## Issue Context
This PR modifies the behavior of `UrlChecker.waitUntilUnavailable`, so it is in-scope for the “complete Javadoc on public API methods” requirement.

## Fix Focus Areas
- java/src/org/openqa/selenium/net/UrlChecker.java[108-114]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Interrupt test doesn’t block 🐞 Bug ≡ Correctness
Description
waitUntilUnavailablePreservesInterruptStatus calls waitUntilUnavailable while the
NettyAppServer created in @BeforeEach is never started, so waitUntilUnavailable can return
immediately on IOException and never throw the expected RuntimeException. As written, the test
can fail (no exception thrown) and does not reliably validate that the interrupt status is preserved
during a blocking wait.
Code

java/test/org/openqa/selenium/net/UrlCheckerTest.java[R106-133]

+  @Test
+  void waitUntilUnavailablePreservesInterruptStatus() throws Exception {
+    Thread caller = Thread.currentThread();
+    Thread interrupter =
+        new Thread(
+            () -> {
+              try {
+                Thread.sleep(500);
+              } catch (InterruptedException ignored) {
+              }
+              caller.interrupt();
+            });
+    interrupter.start();
+
+    boolean threw = false;
+    boolean preserved = false;
+    try {
+      urlChecker.waitUntilUnavailable(10, TimeUnit.SECONDS, url);
+    } catch (RuntimeException expected) {
+      threw = true;
+      preserved = Thread.currentThread().isInterrupted();
+      Thread.interrupted();
+    }
+    interrupter.join();
+
+    assertThat(threw).isTrue();
+    assertThat(preserved).isTrue();
+  }
Evidence
The test’s server is never started, and waitUntilUnavailable returns null immediately on
IOException, so the test may never reach the interruption/exception path it asserts on.

java/test/org/openqa/selenium/net/UrlCheckerTest.java[42-57]
java/test/org/openqa/selenium/net/UrlCheckerTest.java[106-133]
java/src/org/openqa/selenium/net/UrlChecker.java[112-144]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new test intends to verify that interrupt status is preserved when `waitUntilUnavailable` is interrupted while blocked, but it calls `waitUntilUnavailable` when the server is not running. Because `waitUntilUnavailable` treats connection `IOException` as “unavailable” and returns immediately, the test often won’t block long enough to be interrupted and therefore won’t throw the expected `RuntimeException`.

## Issue Context
`@BeforeEach` creates `this.server` and `this.url` but does not start the server. In `UrlChecker.waitUntilUnavailable`, an `IOException` while connecting returns success immediately.

## Fix Focus Areas
- java/test/org/openqa/selenium/net/UrlCheckerTest.java[42-57]
- java/test/org/openqa/selenium/net/UrlCheckerTest.java[106-133]
- java/src/org/openqa/selenium/net/UrlChecker.java[112-163]

## Suggested fix
In `waitUntilUnavailablePreservesInterruptStatus`, start the server (and optionally call `waitUntilAvailable` to ensure it is serving HTTP 200) before invoking `waitUntilUnavailable`, and keep the server running so `waitUntilUnavailable` blocks until the interrupter interrupts the calling thread. Also ensure cleanup (joining interrupter and clearing interrupt) happens even if assertions fail (e.g., via `try/finally`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment on lines +157 to 161
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Action required

1. waituntilunavailable missing javadoc 📘 Rule violation ✧ Quality

The modified public method waitUntilUnavailable(long timeout, TimeUnit unit, URL url) has no
Javadoc block, so its parameters and TimeoutException contract are undocumented. This violates the
requirement for complete Javadoc on changed public API methods.
Agent Prompt
## Issue description
A changed public method `waitUntilUnavailable(...)` lacks a Javadoc block and therefore does not document purpose, `@param` tags, or the `@throws` contract.

## Issue Context
This PR modifies the behavior of `UrlChecker.waitUntilUnavailable`, so it is in-scope for the “complete Javadoc on public API methods” requirement.

## Fix Focus Areas
- java/src/org/openqa/selenium/net/UrlChecker.java[108-114]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +106 to +133
@Test
void waitUntilUnavailablePreservesInterruptStatus() throws Exception {
Thread caller = Thread.currentThread();
Thread interrupter =
new Thread(
() -> {
try {
Thread.sleep(500);
} catch (InterruptedException ignored) {
}
caller.interrupt();
});
interrupter.start();

boolean threw = false;
boolean preserved = false;
try {
urlChecker.waitUntilUnavailable(10, TimeUnit.SECONDS, url);
} catch (RuntimeException expected) {
threw = true;
preserved = Thread.currentThread().isInterrupted();
Thread.interrupted();
}
interrupter.join();

assertThat(threw).isTrue();
assertThat(preserved).isTrue();
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Action required

2. Interrupt test doesn’t block 🐞 Bug ≡ Correctness

waitUntilUnavailablePreservesInterruptStatus calls waitUntilUnavailable while the
NettyAppServer created in @BeforeEach is never started, so waitUntilUnavailable can return
immediately on IOException and never throw the expected RuntimeException. As written, the test
can fail (no exception thrown) and does not reliably validate that the interrupt status is preserved
during a blocking wait.
Agent Prompt
## Issue description
The new test intends to verify that interrupt status is preserved when `waitUntilUnavailable` is interrupted while blocked, but it calls `waitUntilUnavailable` when the server is not running. Because `waitUntilUnavailable` treats connection `IOException` as “unavailable” and returns immediately, the test often won’t block long enough to be interrupted and therefore won’t throw the expected `RuntimeException`.

## Issue Context
`@BeforeEach` creates `this.server` and `this.url` but does not start the server. In `UrlChecker.waitUntilUnavailable`, an `IOException` while connecting returns success immediately.

## Fix Focus Areas
- java/test/org/openqa/selenium/net/UrlCheckerTest.java[42-57]
- java/test/org/openqa/selenium/net/UrlCheckerTest.java[106-133]
- java/src/org/openqa/selenium/net/UrlChecker.java[112-163]

## Suggested fix
In `waitUntilUnavailablePreservesInterruptStatus`, start the server (and optionally call `waitUntilAvailable` to ensure it is serving HTTP 200) before invoking `waitUntilUnavailable`, and keep the server running so `waitUntilUnavailable` blocks until the interrupter interrupts the calling thread. Also ensure cleanup (joining interrupter and clearing interrupt) happens even if assertions fail (e.g., via `try/finally`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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

Labels

C-java Java Bindings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants