Skip to content

tests/conftest: fix concurrent access to pexpect.spawn#1937

Merged
Bastian-Krause merged 1 commit into
labgrid-project:masterfrom
Bastian-Krause:bst/conftest-fix-threaded-pexpect
Jul 16, 2026
Merged

tests/conftest: fix concurrent access to pexpect.spawn#1937
Bastian-Krause merged 1 commit into
labgrid-project:masterfrom
Bastian-Krause:bst/conftest-fix-threaded-pexpect

Conversation

@Bastian-Krause

Copy link
Copy Markdown
Member

Description
Another deep dive into our flaky CI tests:

pexpect/ptyprocess are not thread-safe. But we need a thread to keep reading the Exporter/Coordinator outputs during the tests for debugging purposes.

The reader thread (calling pexpect.spawn.read_nonblocking()) and the main thread (calling pexpect.spawn's kill()/wait()/isalive()) can access it concurrently. Internally, pexpect calls waitpid(2) in these methods.

This behavior leads to errors such as:

ptyprocess.util.PtyProcessError: isalive() encountered condition where "terminated" is 0, but there was no child process. Did someone else call waitpid() on our process?

Or:

pexpect.exceptions.ExceptionPexpect: isalive() encountered condition where "terminated" is 0, but there was no child process. Did someone else call waitpid() on our process?

These errors pop up in CI from time to time: https://github.com/labgrid-project/labgrid/actions/runs/29324126371/job/87056209839

Fix this by serializing access to pexpect.spawn through a lock.

Checklist

  • PR has been tested

Fixes #547

pexpect/ptyprocess are not thread-safe. But we need a thread to keep
reading the Exporter/Coordinator outputs during the tests for debugging
purposes.

The reader thread (calling
`pexpect.spawn.read_nonblocking()`) and the main thread (calling
`pexpect.spawn`'s `kill()`/`wait()`/`isalive()`) can access it
concurrently. Internally, pexpect calls waitpid(2) in these methods.

This behavior leads to errors such as:

  ptyprocess.util.PtyProcessError: isalive() encountered condition where "terminated" is 0, but there was no child process. Did someone else call waitpid() on our process?

Or:

  pexpect.exceptions.ExceptionPexpect: isalive() encountered condition where "terminated" is 0, but there was no child process. Did someone else call waitpid() on our process?

Fix this by serializing access to pexpect.spawn through a lock.

Signed-off-by: Bastian Krause <bst@pengutronix.de>
@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 61.0%. Comparing base (64723a5) to head (66be067).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff            @@
##           master   #1937     +/-   ##
========================================
- Coverage    61.0%   61.0%   -0.1%     
========================================
  Files         182     182             
  Lines       14881   14881             
========================================
- Hits         9083    9081      -2     
- Misses       5798    5800      +2     
Flag Coverage Δ
3.10 61.0% <ø> (-0.1%) ⬇️
3.11 61.0% <ø> (-0.1%) ⬇️
3.12 61.0% <ø> (-0.1%) ⬇️
3.13 60.9% <ø> (-0.1%) ⬇️
3.14 60.9% <ø> (-0.1%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@Bastian-Krause Bastian-Krause added fix pick to stable Needs a pick to the latest stable branch labels Jul 15, 2026
@Bastian-Krause
Bastian-Krause merged commit 4084c8e into labgrid-project:master Jul 16, 2026
10 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix pick to stable Needs a pick to the latest stable branch tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants