Skip to content

Conversation

@titusfortner
Copy link
Member

@titusfortner titusfortner commented Oct 22, 2025

User description

🔗 Related Issues

In the process of this PR - #16476 the (jruby) RBE keeps giving errors. These additions are to minimize IOError during shutdown.

💥 What does this PR do?

  • Changed the order of shutdown actions in bridge and bidi bridge
  • Adds more connection errors to ignore in socket
  • Adds mutex around all the places that may need synchronizing
  • Adds a @closing variable to stop doing things if we want to shut down
  • Joining threads instead of force exiting threads
  • Setting both #abort_on_exception and report_on_exception to false and specifying what we want in the rescue

🔧 Implementation Notes

ngl, I'm not certain we need all of this, but jruby is very picky.
I spent a lot of time consulting/arguing with several LLMs about this and how it fits into where I think we need to go, and learning a lot more about threads and sockets and async than I actually want to know. I'm much more confident about where this sits now.

The main issue is that propagating errors to the main thread isn't a good idea. If the main thread is in an unrelated ruby block when it is interrupted, that block could intercept the standard error unintentionally. There are ways we can manage propagating errors, but this way can cause issues.
Of note Playwright does not throw uncaught exceptions in Python or Java; (just JS where it seems like it's the only option).
This code checks if it is a bidi implementation and just logs the error, which I think is what we want the default to be right now.
I'm keeping existing devtools behavior as-is for backwards compatibility and flagging it as deprecated. Is that too much? Should we just move to the safer logging-only behavior right away?

I've updated it so it logs everything instead of failing it.

We can do something safer more complicated when we move to a slightly different implementation that gives users more control over desired behavior.

🔄 Types of changes

  • Bug fix (backwards compatible)

PR Type

Bug fix


Description

  • Add synchronization with mutex around callback and message operations

  • Expand connection error handling to include EBADF, IOError, EOFError

  • Implement graceful shutdown with @closing flag and thread joining

  • Improve error logging and exception handling in socket listener

  • Reorder quit operations to close bidi before HTTP connection


Diagram Walkthrough

flowchart LR
  A["WebSocket Connection"] -->|add mutex| B["Thread-safe operations"]
  A -->|expand errors| C["CONNECTION_ERRORS list"]
  A -->|graceful shutdown| D["@closing flag + join threads"]
  B -->|protect| E["Callbacks & Messages"]
  C -->|handle| F["EBADF, IOError, EOFError"]
  D -->|replace| G["thread.exit calls"]
  H["Bridge quit"] -->|reorder| I["close bidi first"]
  I -->|then| J["close HTTP"]
Loading

File Walkthrough

Relevant files
Bug fix
websocket_connection.rb
Add mutex synchronization and graceful shutdown handling 

rb/lib/selenium/webdriver/common/websocket_connection.rb

  • Added Errno::EBADF, IOError, and EOFError to CONNECTION_ERRORS list
    for comprehensive error handling
  • Introduced @mtx Mutex and @closing flag for thread-safe
    synchronization
  • Implemented graceful shutdown using thread.join(0.5) instead of
    thread.exit
  • Protected callback and message operations with mutex synchronization
  • Enhanced error logging with debug messages for connection closures and
    callback failures
  • Improved socket.write error handling with try-catch for
    CONNECTION_ERRORS
  • Changed process_handshake to loop until ws.finished? for complete
    handshake
  • Modified attach_socket_listener to use @closing flag and loop instead
    of socket.eof?
  • Updated callback_thread to set abort_on_exception and
    report_on_exception to false with explicit error logging
+65/-35 
bidi_bridge.rb
Reorder quit to close bidi before parent quit                       

rb/lib/selenium/webdriver/remote/bidi_bridge.rb

  • Reordered quit method to close bidi connection before calling super
  • Added rescue clause for QUIT_ERRORS to handle connection errors
    gracefully
  • Changed from ensure block to explicit error handling pattern
+3/-2     
bridge.rb
Expand quit errors and improve close handling                       

rb/lib/selenium/webdriver/remote/bridge.rb

  • Expanded QUIT_ERRORS to include EOFError and WebSocket::Error
  • Changed quit method to use ensure block for http.close instead of
    rescue
  • Wrapped http.close in try-catch for QUIT_ERRORS handling
+7/-4     

@titusfortner titusfortner requested a review from p0deje October 22, 2025 07:29
@selenium-ci selenium-ci added the C-rb Ruby Bindings label Oct 22, 2025
@qodo-merge-pro
Copy link
Contributor

qodo-merge-pro bot commented Oct 22, 2025

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Potential hang

Description: The socket listener loop reads from the socket without a timeout or check for liveness
beyond @closing, which can block indefinitely and potentially hang shutdown if @closing is
never set due to a race; consider using non-blocking reads or timeouts.
websocket_connection.rb [121-143]

Referred Code
Thread.new do
  Thread.current.report_on_exception = false

  loop do
    break if @closing

    incoming_frame << socket.readpartial(1024)

    while (frame = incoming_frame.next)
      break if @closing

      message = process_frame(frame)
      next unless message['method']

      params = message['params']
      @mtx.synchronize { callbacks[message['method']].dup }.each do |callback|
        @callback_threads.add(callback_thread(params, &callback))
      end
    end
  end
rescue *CONNECTION_ERRORS, WebSocket::Error => e


 ... (clipped 2 lines)
Ticket Compliance
🟡
🎫 #1234
🔴 Provide a change that restores the alert/JS execution behavior when clicking such links.
Investigate and fix a regression where clicking a link with JavaScript in href no longer
triggers the JS in Selenium 2.48.x (worked in 2.47.1) on Firefox 42.
Validate behavior specifically in Firefox context labeled in the ticket.
🟡
🎫 #5678
🟢 Provide robust connection handling/logging to diagnose or prevent repeated connection
failures.
Address recurring "Error: ConnectFailure (Connection refused)" when instantiating multiple
ChromeDriver instances on Ubuntu 16.04 with Chrome 65 and ChromeDriver 2.35 using Selenium
3.9.0.
Ensure subsequent ChromeDriver instantiations do not fail with connection refused after
the first instance.
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
No custom compliance provided

Follow the guide to enable custom compliance check.

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-merge-pro
Copy link
Contributor

qodo-merge-pro bot commented Oct 22, 2025

PR Code Suggestions ✨

Latest suggestions up to 627943c

CategorySuggestion                                                                                                                                    Impact
Possible issue
Set closing flag on listener exit

In attach_socket_listener, use an ensure block to set @closing = true when the
listener loop exits, including on error, to ensure a clean shutdown.

rb/lib/selenium/webdriver/common/websocket_connection.rb [128-152]

 def attach_socket_listener
   Thread.new do
     Thread.current.report_on_exception = false
 
-    loop do
-      break if @closing
-
-      incoming_frame << socket.readpartial(1024)
-
-      while (frame = incoming_frame.next)
+    begin
+      loop do
         break if @closing
 
-        message = process_frame(frame)
-        next unless message['method']
+        incoming_frame << socket.readpartial(1024)
 
-        params = message['params']
-        @messages_mtx.synchronize { callbacks[message['method']].dup }.each do |callback|
-          @callback_threads.add(callback_thread(params, &callback))
+        while (frame = incoming_frame.next)
+          break if @closing
+
+          message = process_frame(frame)
+          next unless message['method']
+
+          params = message['params']
+          @callbacks_mtx.synchronize { callbacks[message['method']].dup }.each do |callback|
+            @callback_threads.add(callback_thread(params, &callback))
+          end
         end
       end
+    rescue *CONNECTION_ERRORS, WebSocket::Error => e
+      WebDriver.logger.debug "WebSocket listener closed: #{e.class}: #{e.message}", id: :ws
+    ensure
+      @closing_mtx.synchronize { @closing = true }
     end
-  rescue *CONNECTION_ERRORS, WebSocket::Error => e
-    WebDriver.logger.debug "WebSocket listener closed: #{e.class}: #{e.message}", id: :ws
   end
 end
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly points out that an error in the socket listener should set the @closing flag to signal other threads that the connection is dead, preventing them from waiting indefinitely.

Medium
Enforce safe response timeout

In send_cmd, replace wait.until with a custom wait loop that checks the @closing
flag to avoid waiting for a response when the connection is being terminated.

rb/lib/selenium/webdriver/common/websocket_connection.rb [99-115]

 def send_cmd(**payload)
   id = next_id
   data = payload.merge(id: id)
   WebDriver.logger.debug "WebSocket -> #{data}"[...MAX_LOG_MESSAGE_SIZE], id: :ws
   data = JSON.generate(data)
   out_frame = WebSocket::Frame::Outgoing::Client.new(version: ws.version, data: data, type: 'text')
 
   begin
     socket.write(out_frame.to_s)
   rescue *CONNECTION_ERRORS => e
-    raise e, "WebSocket is closed (#{e.class}: #{e.message})"
+    raise Error::WebDriverError, "WebSocket is closed (#{e.class}: #{e.message})"
   end
 
-  wait.until do
-    @messages_mtx.synchronize { messages.delete(id) }
+  deadline = Time.now + RESPONSE_WAIT_TIMEOUT
+  loop do
+    break if @closing
+    found = @messages_mtx.synchronize { messages.delete(id) }
+    return found if found
+    if Time.now > deadline
+      raise Error::WebDriverError, "Timed out waiting for WebSocket response to command id=#{id}"
+    end
+    sleep RESPONSE_WAIT_INTERVAL
   end
+
+  raise Error::WebDriverError, "Connection closing while waiting for response to command id=#{id}"
 end
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that the wait.until block can wait for the full timeout even if the connection is closing, and proposes adding a check for the @closing flag to fail faster, which improves robustness.

Medium
General
Handle malformed frames safely

In process_frame, wrap JSON.parse in a begin/rescue block to handle
JSON::ParserError, preventing malformed data from crashing the socket listener
thread.

rb/lib/selenium/webdriver/common/websocket_connection.rb [158-169]

 def process_frame(frame)
-  message = frame.to_s
+  raw = frame.to_s
 
   # Firefox will periodically fail on unparsable empty frame
-  return {} if message.empty?
+  return {} if raw.nil? || raw.empty?
 
-  msg = JSON.parse(message)
-  @messages_mtx.synchronize { messages[msg['id']] = msg if msg.key?('id') }
+  begin
+    msg = JSON.parse(raw)
+  rescue JSON::ParserError => e
+    WebDriver.logger.debug "Ignoring unparsable WebSocket frame: #{e.class}: #{e.message}", id: :ws
+    return {}
+  end
+
+  if msg.key?('id')
+    @messages_mtx.synchronize { messages[msg['id']] = msg }
+  end
 
   WebDriver.logger.debug "WebSocket <- #{msg}"[...MAX_LOG_MESSAGE_SIZE], id: :ws
   msg
 end

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies that a JSON::ParserError from a malformed frame would crash the listener thread, and proposes adding error handling to make the connection more resilient.

Medium
Learned
best practice
Guard message fields before use
Suggestion Impact:The commit introduced separate mutexes and began synchronizing access to callbacks/messages. It changed the callback iteration to duplicate callbacks under a dedicated messages mutex, addressing the race concern. However, it did not add the exact type guards for method and params as suggested.

code diff:

@@ -132,9 +138,8 @@
               message = process_frame(frame)
               next unless message['method']
 
-              params = message['params']
-              @mtx.synchronize { callbacks[message['method']].dup }.each do |callback|
-                @callback_threads.add(callback_thread(params, &callback))
+              @messages_mtx.synchronize { callbacks[message['method']].dup }.each do |callback|
+                @callback_threads.add(callback_thread(message['params'], &callback))
               end
             end
           end
@@ -154,7 +159,7 @@
         return {} if message.empty?
 
         msg = JSON.parse(message)
-        @mtx.synchronize { messages[msg['id']] = msg if msg.key?('id') }
+        @messages_mtx.synchronize { messages[msg['id']] = msg if msg.key?('id') }
 
         WebDriver.logger.debug "WebSocket <- #{msg}"[...MAX_LOG_MESSAGE_SIZE], id: :ws

Add defensive checks to ensure message['params'] is a Hash before use and safely
duplicate callbacks to prevent nil errors and races when handlers are removed
concurrently.

rb/lib/selenium/webdriver/common/websocket_connection.rb [137-147]

 while (frame = incoming_frame.next)
   break if @closing
 
   message = process_frame(frame)
-  next unless message['method']
+  method = message['method']
+  next unless method.is_a?(String)
 
   params = message['params']
-  @messages_mtx.synchronize { callbacks[message['method']].dup }.each do |callback|
+  next unless params.is_a?(Hash)
+
+  handlers = @callbacks_mtx.synchronize { callbacks[method].dup }
+  handlers.each do |callback|
     @callback_threads.add(callback_thread(params, &callback))
   end
 end

[Suggestion processed]

Suggestion importance[1-10]: 6

__

Why:
Relevant best practice - Validate inputs and states early to avoid nil errors; guard message handling and callback spawning against missing fields.

Low
  • Update

Previous suggestions

✅ Suggestions up to commit 4292334
CategorySuggestion                                                                                                                                    Impact
High-level
Refactor to use multiple specialized mutexes

Replace the single, coarse-grained mutex with multiple, more granular mutexes,
one for each shared resource (@callbacks, @messages, @closing). This will reduce
lock contention and improve concurrency.

Examples:

rb/lib/selenium/webdriver/common/websocket_connection.rb [40]
        @mtx = Mutex.new
rb/lib/selenium/webdriver/common/websocket_connection.rb [77-80]
        @mtx.synchronize do
          callbacks[event] << block
          block.object_id
        end

Solution Walkthrough:

Before:

class WebSocketConnection
  def initialize(url:)
    @mtx = Mutex.new
    @closing = false
    @callbacks = {}
    @messages = {}
    # ...
  end

  def add_callback(event, &block)
    @mtx.synchronize do
      # ... access @callbacks
    end
  end

  def send_cmd(**payload)
    # ...
    wait.until do
      @mtx.synchronize { messages.delete(id) }
    end
  end

  def process_frame(frame)
    # ...
    @mtx.synchronize { messages[msg['id']] = msg }
    # ...
  end
end

After:

class WebSocketConnection
  def initialize(url:)
    @callbacks_mtx = Mutex.new
    @messages_mtx = Mutex.new
    @closing_mtx = Mutex.new
    @closing = false
    @callbacks = {}
    @messages = {}
    # ...
  end

  def add_callback(event, &block)
    @callbacks_mtx.synchronize do
      # ... access @callbacks
    end
  end

  def send_cmd(**payload)
    # ...
    wait.until do
      @messages_mtx.synchronize { messages.delete(id) }
    end
  end

  def process_frame(frame)
    # ...
    @messages_mtx.synchronize { messages[msg['id']] = msg }
    # ...
  end
end
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies that a single coarse-grained mutex is used to protect multiple independent resources, which can cause unnecessary lock contention and performance issues. Adopting a more granular locking strategy is a significant architectural improvement for the concurrency model introduced in this PR.

Medium
Possible issue
Ensure session is always deleted
Suggestion Impact:The commit changed the quit method so that failures from bidi.close are rescued and super is guaranteed to run via an ensure block, ensuring session cleanup. Although it used an ensure block instead of wrapping only bidi.close in a begin/rescue, it achieved the same goal of always calling super even if bidi.close fails.

code diff:

         def quit
           bidi.close
-          super
         rescue *QUIT_ERRORS
           nil
+        ensure
+          super
         end

Modify the quit method to ensure super is always called, even if bidi.close
fails. Wrap only the bidi.close call in a begin/rescue block to prevent leaving
orphaned browser sessions.

rb/lib/selenium/webdriver/remote/bidi_bridge.rb [48-53]

 def quit
-  bidi.close
+  begin
+    bidi.close
+  rescue *QUIT_ERRORS
+    nil
+  end
   super
-rescue *QUIT_ERRORS
-  nil
 end

[Suggestion processed]

Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies a critical flaw where a failure in bidi.close would prevent the super call from executing, potentially leaving browser sessions running. The proposed fix ensures the session is always cleaned up.

Medium
Fix race condition in callback removal
Suggestion Impact:The commit changed remove_callback to wrap the closing check, removal, and ID collection within a single @callbacks_mtx.synchronize block, addressing the race condition as suggested.

code diff:

       def remove_callback(event, id)
-        removed = @mtx.synchronize { callbacks[event].reject! { |cb| cb.object_id == id } }
-        return if removed || @closing
-
-        ids = @mtx.synchronize { callbacks[event]&.map(&:object_id) }
-        raise Error::WebDriverError, "Callback with ID #{id} does not exist for event #{event}: #{ids}"
+        @callbacks_mtx.synchronize do
+          return if @closing
+
+          callbacks_for_event = callbacks[event]
+          return if callbacks_for_event.reject! { |cb| cb.object_id == id }
+
+          ids = callbacks[event]&.map(&:object_id)
+          raise Error::WebDriverError, "Callback with ID #{id} does not exist for event #{event}: #{ids}"
+        end
       end

Refactor the remove_callback method to use a single synchronize block. This will
prevent a race condition by ensuring the callback removal and error message data
collection are performed atomically.

rb/lib/selenium/webdriver/common/websocket_connection.rb [84-88]

-removed = @mtx.synchronize { callbacks[event].reject! { |cb| cb.object_id == id } }
-return if removed || @closing
+@mtx.synchronize do
+  return if @closing
 
-ids = @mtx.synchronize { callbacks[event]&.map(&:object_id) }
-raise Error::WebDriverError, "Callback with ID #{id} does not exist for event #{event}: #{ids}"
+  callbacks_for_event = callbacks[event]
+  if callbacks_for_event.reject! { |cb| cb.object_id == id }
+    return
+  end
 
+  ids = callbacks_for_event.map(&:object_id)
+  raise Error::WebDriverError, "Callback with ID #{id} does not exist for event #{event}: #{ids}"
+end
+

[Suggestion processed]

Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies a race condition in the remove_callback method where two separate synchronize blocks could lead to inconsistent state, and proposes a valid fix by using a single atomic block.

Medium
Learned
best practice
Make handshake loop safe

Guard the handshake read loop against connection closure and IO errors so
resources don't hang if the socket closes mid-handshake.

rb/lib/selenium/webdriver/common/websocket_connection.rb [115-118]

 def process_handshake
   socket.print(ws.to_s)
-  ws << socket.readpartial(1024) until ws.finished?
+  begin
+    ws << socket.readpartial(1024) until ws.finished?
+  rescue *CONNECTION_ERRORS, WebSocket::Error, EOFError, IOError
+    # let caller handle a failed/closed handshake deterministically
+    raise Error::WebDriverError, 'WebSocket handshake failed or connection closed'
+  end
 end
Suggestion importance[1-10]: 6

__

Why:
Relevant best practice - Enforce deterministic and safe resource handling by ensuring sockets/threads are always cleaned up on all code paths.

Low

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds thread safety and improved error handling to WebSocket connection management in the Ruby Selenium bindings to prevent IOError exceptions during JRuby shutdown. The changes focus on synchronizing concurrent access to shared resources, gracefully handling connection errors, and properly coordinating shutdown sequences.

Key changes:

  • Added mutex synchronization around all WebSocket callback and message operations
  • Expanded connection error handling to include EBADF, IOError, and EOFError
  • Implemented graceful shutdown using thread joining instead of forced exits

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
websocket_connection.rb Added mutex synchronization, graceful shutdown with @closing flag, and enhanced error handling for socket operations
bidi_bridge.rb Reordered quit sequence to close BiDi connection before parent HTTP connection
bridge.rb Expanded QUIT_ERRORS list and improved error handling in quit method
test_environment.rb Added --disable-dev-shm-usage flag for Chrome/Edge when running on RBE
driver_spec.rb Simplified test exclusion metadata

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@titusfortner titusfortner force-pushed the rb_socket_fixes branch 2 times, most recently from 11def6f to 627943c Compare October 23, 2025 18:24
@qodo-merge-pro
Copy link
Contributor

CI Feedback 🧐

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: Ruby / Unit Tests (3.2.8, windows) / Unit Tests (3.2.8, windows)

Failed stage: Run Bazel [❌]

Failed test name: //rb/spec/unit/selenium/webdriver/common/interactions:pointer_cancel

Failure summary:

The GitHub Action failed because a Bazel test timed out:
- Test target
//rb/spec/unit/selenium/webdriver/common/interactions:pointer_cancel hit the 1800s timeout and did
not complete.
- Bazel summary shows: "Build completed, 1 test FAILED" with the single failure being
a TIMEOUT.
- Test log path:
D:/b/execroot/_main/bazel-out/x64_windows-fastbuild/testlogs/rb/spec/unit/selenium/webdriver/common/interactions/pointer_cancel/test.log

- All other 66 tests passed; only this one timed out, causing the overall job to exit with code 1.

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

567:  -> Locally signed 5 keys.
568:  ==> Importing owner trust values...
569:  gpg: setting ownertrust to 4
570:  gpg: setting ownertrust to 4
571:  gpg: setting ownertrust to 4
572:  gpg: setting ownertrust to 4
573:  gpg: setting ownertrust to 4
574:  ==> Disabling revoked keys in keyring...
575:  �[35mWARNING: �[0mD:/b/external/io_bazel_rules_closure/java/com/google/javascript/jscomp/BUILD:19:13: in java_library rule @@io_bazel_rules_closure//java/com/google/javascript/jscomp:jscomp: target '@@io_bazel_rules_closure//java/com/google/javascript/jscomp:jscomp' depends on deprecated target '@@io_bazel_rules_closure//java/io/bazel/rules/closure:build_info_java_proto': Use java_proto_library from com_google_protobuf
576:  -> Disabled 4 keys.
577:  ==> Updating trust database...
578:  gpg: marginals needed: 3  completes needed: 1  trust model: pgp
579:  gpg: depth: 0  valid:   1  signed:   5  trust: 0-, 0q, 0n, 0m, 0f, 1u
580:  gpg: depth: 1  valid:   5  signed:   6  trust: 0-, 0q, 0n, 5m, 0f, 0u
581:  gpg: depth: 2  valid:   3  signed:   2  trust: 3-, 0q, 0n, 0m, 0f, 0u
582:  gpg: error retrieving '[email protected]' via WKD: No data
583:  gpg: error reading key: No data
584:  gpg: refreshing 1 key from hkps://keyserver.ubuntu.com
585:  gpg: key F40D263ECA25678A: "Alexey Pavlov (Alexpux) <[email protected]>" not changed
586:  gpg: Total number processed: 1
587:  gpg:              unchanged: 1
588:  gpg: error retrieving '[email protected]' via WKD: Try again later
589:  gpg: error reading key: Try again later
590:  gpg: refreshing 1 key from hkps://keyserver.ubuntu.com
591:  gpg: key 790AE56A1D3CFDDC: "David Macek (MSYS2 master key) <[email protected]>" not changed
592:  gpg: Total number processed: 1
593:  gpg:              unchanged: 1
594:  gpg: error retrieving '[email protected]' via WKD: Try again later
595:  gpg: error reading key: Try again later
596:  gpg: refreshing 1 key from hkps://keyserver.ubuntu.com
597:  gpg: key DA7EF2ABAEEA755C: "Martell Malone (martell) <[email protected]>" not changed
598:  gpg: Total number processed: 1
599:  gpg:              unchanged: 1
600:  gpg: error retrieving '[email protected]' via WKD: Try again later
601:  gpg: error reading key: Try again later
602:  gpg: refreshing 1 key from hkps://keyserver.ubuntu.com
603:  gpg: key 755B8182ACD22879: "Christoph Reiter (MSYS2 master key) <[email protected]>" not changed
604:  gpg: Total number processed: 1
605:  gpg:              unchanged: 1
606:  gpg: error retrieving '[email protected]' via WKD: Try again later
607:  gpg: error reading key: Try again later
608:  gpg: refreshing 1 key from hkps://keyserver.ubuntu.com
609:  gpg: key 9F418C233E652008: "Ignacio Casal Quinteiro <[email protected]>" not changed
610:  gpg: Total number processed: 1
611:  gpg:              unchanged: 1
612:  gpg: error retrieving '[email protected]' via WKD: Try again later
613:  gpg: error reading key: Try again later
614:  gpg: refreshing 1 key from hkps://keyserver.ubuntu.com
615:  gpg: key BBE514E53E0D0813: "Ray Donnelly (MSYS2 Developer - master key) <[email protected]>" not changed
616:  gpg: Total number processed: 1
617:  gpg:              unchanged: 1
618:  gpg: error retrieving '[email protected]' via WKD: Try again later
619:  gpg: error reading key: Try again later
620:  gpg: refreshing 1 key from hkps://keyserver.ubuntu.com
621:  gpg: key 5F92EFC1A47D45A1: "Alexey Pavlov (Alexpux) <[email protected]>" not changed
622:  gpg: Total number processed: 1
623:  gpg:              unchanged: 1
624:  gpg: error retrieving '[email protected]' via WKD: No data
625:  gpg: error reading key: No data
626:  gpg: refreshing 1 key from hkps://keyserver.ubuntu.com
627:  gpg: key 974C8BE49078F532: "David Macek <[email protected]>" 3 new signatures
628:  gpg: key 974C8BE49078F532: "David Macek <[email protected]>" 1 signature cleaned
629:  gpg: Total number processed: 1
630:  gpg:         new signatures: 3
631:  gpg:     signatures cleaned: 1
632:  gpg: marginals needed: 3  completes needed: 1  trust model: pgp
633:  gpg: depth: 0  valid:   1  signed:   5  trust: 0-, 0q, 0n, 0m, 0f, 1u
634:  gpg: depth: 1  valid:   5  signed:   7  trust: 0-, 0q, 0n, 5m, 0f, 0u
635:  gpg: depth: 2  valid:   4  signed:   2  trust: 4-, 0q, 0n, 0m, 0f, 0u
636:  gpg: next trustdb check due at 2026-04-10
637:  gpg: error retrieving '[email protected]' via WKD: Try again later
638:  gpg: error reading key: Try again later
639:  gpg: refreshing 1 key from hkps://keyserver.ubuntu.com
640:  gpg: key FA11531AA0AA7F57: "Christoph Reiter (MSYS2 development key) <[email protected]>" not changed
641:  gpg: Total number processed: 1
642:  gpg:              unchanged: 1
643:  gpg: error retrieving '[email protected]' via WKD: Unknown host
644:  gpg: error reading key: Unknown host
645:  gpg: refreshing 1 key from hkps://keyserver.ubuntu.com
646:  gpg: key 794DCF97F93FC717: "Martell Malone (martell) <[email protected]>" not changed
647:  gpg: Total number processed: 1
648:  gpg:              unchanged: 1
649:  gpg: error retrieving '[email protected]' via WKD: Try again later
650:  gpg: error reading key: Try again later
651:  gpg: refreshing 1 key from hkps://keyserver.ubuntu.com
652:  gpg: key D595C9AB2C51581E: "Martell Malone (MSYS2 Developer) <[email protected]>" not changed
653:  gpg: Total number processed: 1
654:  gpg:              unchanged: 1
655:  gpg: error retrieving '[email protected]' via WKD: Try again later
656:  gpg: error reading key: Try again later
657:  gpg: refreshing 1 key from hkps://keyserver.ubuntu.com
...

847:  cl : Command line warning D9002 : ignoring unknown option '-std=c++14'
848:  �[32mINFO: �[0mFrom Compiling upb_generator/minitable/names.cc [for tool]:
849:  cl : Command line warning D9002 : ignoring unknown option '-std=c++14'
850:  �[32mINFO: �[0mFrom Compiling upb_generator/minitable/names_internal.cc [for tool]:
851:  cl : Command line warning D9002 : ignoring unknown option '-std=c++14'
852:  �[32mINFO: �[0mFrom Compiling absl/crc/internal/crc.cc [for tool]:
853:  cl : Command line warning D9002 : ignoring unknown option '-std=c++14'
854:  �[32mINFO: �[0mFrom Compiling absl/crc/internal/crc_x86_arm_combined.cc [for tool]:
855:  cl : Command line warning D9002 : ignoring unknown option '-std=c++14'
856:  �[32mINFO: �[0mFrom Compiling absl/profiling/internal/exponential_biased.cc [for tool]:
857:  cl : Command line warning D9002 : ignoring unknown option '-std=c++14'
858:  �[32mINFO: �[0mFrom Compiling absl/strings/internal/cordz_functions.cc [for tool]:
859:  cl : Command line warning D9002 : ignoring unknown option '-std=c++14'
860:  �[32mINFO: �[0mFrom Compiling upb_generator/common/names.cc [for tool]:
861:  cl : Command line warning D9002 : ignoring unknown option '-std=c++14'
862:  �[32mINFO: �[0mFrom Compiling absl/base/internal/strerror.cc [for tool]:
863:  cl : Command line warning D9002 : ignoring unknown option '-std=c++14'
...

2030:  �[32m[1,271 / 1,272]�[0m 66 / 67 tests;�[0m Testing //rb/spec/unit/selenium/webdriver/common/interactions:pointer_cancel; 1484s local, disk-cache
2031:  �[32m[1,271 / 1,272]�[0m 66 / 67 tests;�[0m Testing //rb/spec/unit/selenium/webdriver/common/interactions:pointer_cancel; 1544s local, disk-cache
2032:  �[32m[1,271 / 1,272]�[0m 66 / 67 tests;�[0m Testing //rb/spec/unit/selenium/webdriver/common/interactions:pointer_cancel; 1605s local, disk-cache
2033:  �[32m[1,271 / 1,272]�[0m 66 / 67 tests;�[0m Testing //rb/spec/unit/selenium/webdriver/common/interactions:pointer_cancel; 1665s local, disk-cache
2034:  �[32m[1,271 / 1,272]�[0m 66 / 67 tests;�[0m Testing //rb/spec/unit/selenium/webdriver/common/interactions:pointer_cancel; 1725s local, disk-cache
2035:  �[32m[1,271 / 1,272]�[0m 66 / 67 tests;�[0m Testing //rb/spec/unit/selenium/webdriver/common/interactions:pointer_cancel; 1785s local, disk-cache
2036:  �[32m[1,271 / 1,272]�[0m 66 / 67 tests;�[0m Testing //rb/spec/unit/selenium/webdriver/common/interactions:pointer_cancel; 1800s local, disk-cache
2037:  �[31m�[1mTIMEOUT: �[0m//rb/spec/unit/selenium/webdriver/common/interactions:pointer_cancel (Summary)
2038:  D:/b/execroot/_main/bazel-out/x64_windows-fastbuild/testlogs/rb/spec/unit/selenium/webdriver/common/interactions/pointer_cancel/test.log
2039:  �[32mINFO: �[0mFrom Testing //rb/spec/unit/selenium/webdriver/common/interactions:pointer_cancel:
2040:  ==================== Test output for //rb/spec/unit/selenium/webdriver/common/interactions:pointer_cancel:
2041:  ================================================================================
2042:  �[32mINFO: �[0mFound 67 test targets...
2043:  �[32mINFO: �[0mElapsed time: 2408.243s, Critical Path: 2272.73s
2044:  �[32mINFO: �[0m1272 processes: 552 disk cache hit, 577 internal, 143 local.
2045:  �[32mINFO: �[0mBuild completed, 1 test FAILED, 1272 total actions
2046:  //rb/spec/unit/selenium:devtools                                         �[0m�[32mPASSED�[0m in 5.8s
...

2099:  //rb/spec/unit/selenium/webdriver/ie:service                             �[0m�[32mPASSED�[0m in 4.6s
2100:  //rb/spec/unit/selenium/webdriver/remote:bridge                          �[0m�[32mPASSED�[0m in 6.5s
2101:  //rb/spec/unit/selenium/webdriver/remote:capabilities                    �[0m�[32mPASSED�[0m in 5.4s
2102:  //rb/spec/unit/selenium/webdriver/remote:driver                          �[0m�[32mPASSED�[0m in 5.4s
2103:  //rb/spec/unit/selenium/webdriver/remote/http:common                     �[0m�[32mPASSED�[0m in 5.2s
2104:  //rb/spec/unit/selenium/webdriver/remote/http:curb                       �[0m�[32mPASSED�[0m in 5.0s
2105:  //rb/spec/unit/selenium/webdriver/remote/http:default                    �[0m�[32mPASSED�[0m in 5.0s
2106:  //rb/spec/unit/selenium/webdriver/safari:driver                          �[0m�[32mPASSED�[0m in 5.7s
2107:  //rb/spec/unit/selenium/webdriver/safari:options                         �[0m�[32mPASSED�[0m in 5.0s
2108:  //rb/spec/unit/selenium/webdriver/safari:service                         �[0m�[32mPASSED�[0m in 4.7s
2109:  //rb/spec/unit/selenium/webdriver/support:color                          �[0m�[32mPASSED�[0m in 5.4s
2110:  //rb/spec/unit/selenium/webdriver/support:event_firing                   �[0m�[32mPASSED�[0m in 6.5s
2111:  //rb/spec/unit/selenium/webdriver/support:select                         �[0m�[32mPASSED�[0m in 5.5s
2112:  //rb/spec/unit/selenium/webdriver/common/interactions:pointer_cancel    �[0m�[31m�[1mTIMEOUT�[0m in 1800.0s
2113:  D:/b/execroot/_main/bazel-out/x64_windows-fastbuild/testlogs/rb/spec/unit/selenium/webdriver/common/interactions/pointer_cancel/test.log
2114:  Executed 67 out of 67 tests: 66 tests pass and �[0m�[31m�[1m1 fails locally�[0m.
2115:  �[0m
2116:  ##[error]Process completed with exit code 1.
2117:  Post job cleanup.

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.

2 participants