Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overhaul handling of transfer errors and use of streaming flag. #1069

Merged
merged 10 commits into from
Jun 14, 2022

Conversation

martinling
Copy link
Member

@martinling martinling commented Mar 18, 2022

This PR ensures correct behaviour during shutdown, and reviews and simplifies usage of the streaming and do_exit flags. The changes are as follows:

  • The transfer callback no longer calls request_exit() to end the transfer thread if an error occurs. It was no longer safe to do this after the changes in Fixes for concurrency bugs in start/stop operations #1029, because we need the transfer thread to keep running, to handle cancellations and signal when these are complete. Instead, if it sees an error, the callback just records the transfer as finished, and clears the streaming flag. This fixes libhackrf hangs if HackRF is disconnected #1068.
  • The transfer callback will no longer call the user RX callback, or submit further transfers, once the streaming flag is cleared. This ensures that:
    • Once the RX callback returns nonzero to indicate completion, it is not called again with further in-flight transfers.
    • After any libusb error occurs, no further RX callbacks are made and no more transfers are submitted.
  • Review, correct and simplify all the cases where we set or clear streaming and do_exit. The result is:
    • The streaming flag is:
      • Set in prepare_transfers, which is called via prepare_setup_transfers by:
        • hackrf_start_tx
        • hackrf_start_rx
        • hackrf_start_rx_sweep
      • Cleared in cancel_transfers, which is called by:
        • hackrf_stop_tx
        • hackrf_stop_rx
        • hackrf_close via kill_transfer_thread
      • Cleared in transfer_finished, which is called by hackrf_libusb_transfer_callback if any transfer finishes without being successfully resubmitted.
      • Cleared in transfer_threadproc if libusb_handle_events_timeout returns an error.
    • The do_exit flag is set only in kill_transfer_thread, which is called only from hackrf_close. The flag is cleared again after joining the thread.

In the case of a libusb error, we still need the transfer thread
running, in order to handle outstanding cancellations and to signal the
condition variable when that is done.
If result < 0 here, libusb_submit_transfer returned an error, so we
need to shut down.

If !resubmit, then cancel_transfers() was already called by one of the
stop or close functions, so streaming is already false.
This stops the RX callback from being called again with further data
once it has returned nonzero, or after a transfer had an error status.
If a transfer was cancelled, we are on our way to shutdown.

If hackrf_stop_tx() or hackrf_stop_rx() were called, they will already
have cleared this flag, but it is not cleared in hackrf_close(), and
for consistency with other paths it makes sense to clear it here.
Since we always do these together, move it into the function.
There are now only two possible outcomes to this function: either we
successfully resubmitted a transfer, or the transfer is finished and we
end up calling transfer_finished().

So we can go ahead and simplify it accordingly.
Moving this into cancel_transfers() avoids duplicating it in the two
stop functions.
Avoids conditionally duplicating this across three other places.
This simplifies prepare_setup_transfers(), which was just setting
the flag if prepare_transfers() returned success, and passing on
its return value.
This just set the do_exit flag, and was now only called in one place.
@metayan
Copy link

metayan commented Mar 23, 2022

Tested on Linux (funtoo) and Darwin (10.15.7).
Nice.

@martinling martinling added this to the 2022 release milestone Jun 13, 2022
Copy link
Member

@mossmann mossmann left a comment

Choose a reason for hiding this comment

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

Wonderful!

@mossmann mossmann merged commit a41c807 into greatscottgadgets:master Jun 14, 2022
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.

libhackrf hangs if HackRF is disconnected
3 participants