Skip to content

fix: Fix ValueError in signal handling for Trino worker threads#6428

Open
mbm-codes wants to merge 2 commits into
feast-dev:masterfrom
mbm-codes:fix/trino-signal-worker-thread
Open

fix: Fix ValueError in signal handling for Trino worker threads#6428
mbm-codes wants to merge 2 commits into
feast-dev:masterfrom
mbm-codes:fix/trino-signal-worker-thread

Conversation

@mbm-codes
Copy link
Copy Markdown

@mbm-codes mbm-codes commented May 21, 2026

What this PR does / why we need it:

Guards signal.signal() calls in Query.__init__() with a threading.current_thread() is threading.main_thread() check.

When the Trino offline store is served via Arrow Flight, Query.__init__() runs in a worker thread. Python restricts signal.signal() to the main thread only, causing:
ValueError: signal only works in main thread of the main interpreter

Which issue(s) this PR fixes:

Fixes #6424

Checks

  • I've made sure the tests are passing.
  • My commits are signed off (git commit -s)
  • My PR title follows conventional commits format

Testing Strategy

  • Unit tests

Misc

Added regression tests covering both main thread and worker thread scenarios.
Signal handling is preserved for CLI/interactive usage. Worker thread usage silently skips signal registration, which is the correct behavior when running under Arrow Flight.

Signed-off-by: MBM <mihir105@gmail.com>
@mbm-codes mbm-codes requested a review from a team as a code owner May 21, 2026 11:03
@mbm-codes mbm-codes changed the title Fix ValueError in signal handling for Trino worker threads fix: Fix ValueError in signal handling for Trino worker threads May 21, 2026
@franciscojavierarceo
Copy link
Copy Markdown
Member

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a147b7de22

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

"""signal.signal() should work fine in main thread."""
cursor = MagicMock()
# Should not raise any exception in main thread
query = Query(query_text="SELECT 1", cursor=cursor)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Restore process signal handlers after the test

When this test runs, Query.__init__ installs process-global SIGINT/SIGTERM handlers that point at this test's mock cursor, and the test never restores the previous handlers. Any later test or CI shutdown signal in the same pytest process can be intercepted by query.cancel() instead of the runner's normal KeyboardInterrupt/termination handling, which can make the rest of the suite ignore interrupts or hang until forcibly killed. Patch signal.signal in this test or save and restore the old handlers in a finally.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good catch

Copy link
Copy Markdown
Collaborator

@jyejare jyejare left a comment

Choose a reason for hiding this comment

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

This PR fixes a ValueError that occurs when Query objects are instantiated in worker threads by guarding signal.signal() calls with a main thread check. The fix is simple and effective, with good test coverage demonstrating both main thread and worker thread scenarios.

Comment on lines +15 to +17
query = Query(query_text="SELECT 1", cursor=cursor)
assert query.query_text == "SELECT 1"
# Expected signal.signal to be called twice for SIGINT and SIGTERM
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] Test should verify signal handler registration details

The test only checks call_count but should also verify that the correct signals and handler function are being registered for more thorough validation.

Current code:

+        # Expected signal.signal to be called twice for SIGINT and SIGTERM
+        assert mock_signal.call_count == 2

Suggested:

Suggested change
query = Query(query_text="SELECT 1", cursor=cursor)
assert query.query_text == "SELECT 1"
# Expected signal.signal to be called twice for SIGINT and SIGTERM
# Verify signal handlers are registered correctly
assert mock_signal.call_count == 2
mock_signal.assert_any_call(signal.SIGINT, query.cancel)
mock_signal.assert_any_call(signal.SIGTERM, query.cancel)

Comment on lines +40 to +41

assert not errors, f"Unexpected ValueError in worker thread: {errors[0]}"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] Improve error message handling

The error message assumes errors[0] exists, but this could cause an IndexError if errors is empty. Consider a more defensive approach.

Current code:

+    assert not errors, f"Unexpected ValueError in worker thread: {errors[0]}"

Suggested:

Suggested change
assert not errors, f"Unexpected ValueError in worker thread: {errors[0]}"
assert not errors, f"Unexpected ValueError in worker thread: {errors[0] if errors else 'No errors captured'}"

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.

Bug Report: signal.signal() fails in Arrow Flight worker thread in Trino offline store

3 participants