Skip to content

Fix SELECT on tables with bytea columns hanging in process worker#171

Merged
Maxteabag merged 1 commit intoMaxteabag:mainfrom
AlexZeitler:fix/bytea-memoryview-pickle-hang
Apr 18, 2026
Merged

Fix SELECT on tables with bytea columns hanging in process worker#171
Maxteabag merged 1 commit intoMaxteabag:mainfrom
AlexZeitler:fix/bytea-memoryview-pickle-hang

Conversation

@AlexZeitler
Copy link
Copy Markdown
Contributor

Summary

  • psycopg2 returns memoryview objects for bytea columns which cannot be pickled through multiprocessing.Pipe
  • The worker's send() silently swallowed the serialization error, leaving the client waiting forever (spinner)
  • Convert memoryview to bytes in CursorBasedAdapter.execute_query() before rows are returned, so they can be safely pickled
  • Added unit tests for the sanitization logic

Test plan

  • Unit tests for _sanitize_cell and _sanitize_row pass
  • Connect to PostgreSQL 17
  • Create table with bytea column and insert rows (see setup SQL in SELECT on table with bytea column hangs when executed as single statement #161)
  • Run SELECT * FROM bytea_repro; as single statement — should return 3 rows immediately
  • Run SELECT id, name FROM bytea_repro; — should still work
  • Run both statements together — should still work

Fixes #161

psycopg2 returns memoryview objects for bytea columns which cannot be
pickled through multiprocessing.Pipe. The worker's send() silently
swallowed the serialization error, leaving the client waiting forever.

Convert memoryview to bytes in CursorBasedAdapter.execute_query() before
rows are returned, so they can be safely pickled.

Fixes Maxteabag#161
@Maxteabag
Copy link
Copy Markdown
Owner

Thanks for the PR!

@Maxteabag Maxteabag merged commit 41f6f58 into Maxteabag:main Apr 18, 2026
Maxteabag added a commit that referenced this pull request Apr 18, 2026
#161's symptom was an indefinite spinner: psycopg2 returned memoryview
for bytea, which couldn't be pickled across multiprocessing.Pipe.
_WorkerState.send caught the exception and silently dropped it, so the
client's recv() waited forever.

#171 fixed the specific memoryview case at the adapter, but the silent
swallow is still a trap for any other non-picklable cell type a future
driver might return. Narrow the catch: on pickle errors, replace the
payload with an error message (keyed to the original query id) so the
client surfaces it.

Tests pin the scenarios that were previously gaps:
- CursorBasedAdapter.execute_query actually calls _sanitize_row
  (guards against a future revert of the call site).
- Sanitized rows round-trip through pickle.
- _WorkerState.send with a non-picklable payload delivers an error
  message within a short timeout.
- Picklable payloads still pass through unchanged.
@AlexZeitler
Copy link
Copy Markdown
Contributor Author

Thanks for merging!

@AlexZeitler AlexZeitler deleted the fix/bytea-memoryview-pickle-hang branch April 19, 2026 10:35
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.

SELECT on table with bytea column hangs when executed as single statement

2 participants