Skip to content

Conversation

@realh4m
Copy link

@realh4m realh4m commented Nov 27, 2025

Description

Added exception tracking in process_video so callback errors raised in the worker loop are surfaced after reader/writer threads finish, preventing silent hangs when the callback crashes mid-stream.

Introduced read_finished to avoid draining the read queue unnecessarily once EOF is reached.

  • Issue: Fixes the silent failure where process_video could hang without any error when the callback raised an exception.
  • Dependencies: None.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update

How has this change been tested, please provide a testcase or example of how you tested the change?

Verified locally with a callback that raises an exception.

Any specific deployment considerations

No additional considerations; behavior change only affects process_video error handling.

Docs

  • Docs updated? What were the changes:

@realh4m realh4m requested a review from SkalskiP as a code owner November 27, 2025 11:03
@realh4m realh4m changed the title Fix process_video silent hang on callback error fix: process_video silent hang on callback error Nov 27, 2025
@CLAassistant
Copy link

CLAassistant commented Nov 27, 2025

CLA assistant check
All committers have signed the CLA.

@Borda
Copy link
Member

Borda commented Jan 15, 2026

@realh4m, thank you for your contribution and suggested fix. Could you also include a test to verify that it resolves the issue? 🦩

@Borda Borda changed the title fix: process_video silent hang on callback error fix: process_video silent hang on callback error Jan 15, 2026
Copy link
Contributor

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 fixes a silent hang issue in process_video when the callback function raises an exception during video processing. The fix ensures that exceptions are caught, the pipeline is properly shut down, and the error is re-raised to the caller.

Changes:

  • Added exception tracking (exception_in_worker) to capture and re-raise callback errors
  • Introduced read_finished flag to conditionally drain the read queue in the finally block
  • Modified the finally block to drain remaining frames from the read queue when an exception occurs, preventing deadlock

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +318 to 323
except Exception as exc:
exception_in_worker = exc
break

frame_write_queue.put(processed_frame)
progress_bar.update(1)
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

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

When an exception occurs in the callback (line 318-320), the code breaks out of the loop without putting the processed frame into frame_write_queue. However, the frame_write_queue.put(processed_frame) statement at line 322 is unreachable after the break statement at line 320. This is correct behavior, but there's a potential issue: if the exception occurs, no frame is written to the write queue for that iteration, but the progress bar was already updated. The progress bar should only be updated after successful processing and queuing. Consider moving progress_bar.update(1) inside the try block after line 322 to ensure it only updates on success.

Suggested change
except Exception as exc:
exception_in_worker = exc
break
frame_write_queue.put(processed_frame)
progress_bar.update(1)
frame_write_queue.put(processed_frame)
progress_bar.update(1)
except Exception as exc:
exception_in_worker = exc
break

Copilot uses AI. Check for mistakes.
Comment on lines +326 to +330
if not read_finished:
while True:
read_item = frame_read_queue.get()
if read_item is None:
break
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

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

The drain loop uses a blocking get() which could potentially hang if the reader thread has crashed or is otherwise unable to send the terminating None sentinel. Consider using get(timeout=...) with an appropriate timeout to prevent indefinite blocking in edge cases where the reader thread fails unexpectedly.

Copilot uses AI. Check for mistakes.
Comment on lines +318 to 323
except Exception as exc:
exception_in_worker = exc
break

frame_write_queue.put(processed_frame)
progress_bar.update(1)
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

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

The variable processed_frame is only assigned inside the try block. If an exception occurs before it's assigned (which is the purpose of this exception handling), the code at line 322 would reference an undefined variable, causing a NameError. However, since line 320 breaks out of the loop when an exception is caught, line 322 is never reached in the exception case. This code structure is confusing and fragile. Consider moving line 322 inside the try block, right after line 317, to make the control flow clearer and ensure the frame is only queued if processing succeeds.

Suggested change
except Exception as exc:
exception_in_worker = exc
break
frame_write_queue.put(processed_frame)
progress_bar.update(1)
frame_write_queue.put(processed_frame)
progress_bar.update(1)
except Exception as exc:
exception_in_worker = exc
break

Copilot uses AI. Check for mistakes.
@realh4m realh4m force-pushed the fix/video-worker-error-propagation branch from 0406081 to fce63f8 Compare January 15, 2026 14:31
@realh4m
Copy link
Author

realh4m commented Jan 15, 2026

Thank you for the feedback. I've added unit tests in test/utils/test_video.py to verify that process_video now correctly raises exceptions without hanging. I also included tests for general video utility functions and fixed a minor typo in the process_video docstring. All tests passed successfully.

@codecov
Copy link

codecov bot commented Jan 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (develop@7f7b25d). Learn more about missing BASE report.

Additional details and impacted files
@@            Coverage Diff            @@
##             develop   #2022   +/-   ##
=========================================
  Coverage           ?     53%           
=========================================
  Files              ?      61           
  Lines              ?    7090           
  Branches           ?       0           
=========================================
  Hits               ?    3746           
  Misses             ?    3344           
  Partials           ?       0           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

3 participants