Skip to content

Commit

Permalink
fruity: Fix hang when a USB op starts at teardown
Browse files Browse the repository at this point in the history
Which would result in such transfers never completing, as our USB worker
is no longer processing libusb events.

Kudos to @mrmacete for helping track this one down.

Co-authored-by: Håvard Sørbø <havard@hsorbo.no>
  • Loading branch information
oleavr and hsorbo committed Nov 13, 2024
1 parent 4fce1c4 commit ec58296
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 10 deletions.
42 changes: 33 additions & 9 deletions src/fruity/device-monitor.vala
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,8 @@ namespace Frida.Fruity {
}

public async void start (Cancellable? cancellable) throws IOError {
state = STARTING;
lock (state)
state = STARTING;

usb_worker = new Thread<void> ("frida-core-device-usb", perform_usb_work);

Expand All @@ -782,11 +783,13 @@ namespace Frida.Fruity {
assert_not_reached ();
}

state = STARTED;
lock (state)
state = STARTED;
}

public async void stop (Cancellable? cancellable) throws IOError {
state = FLUSHING;
lock (state)
state = FLUSHING;

io_cancellable.cancel ();

Expand Down Expand Up @@ -814,7 +817,8 @@ namespace Frida.Fruity {

usb_context = null;

state = STOPPED;
lock (state)
state = STOPPED;
}

public async void activate_modeswitch_support (Cancellable? cancellable) throws IOError {
Expand Down Expand Up @@ -911,7 +915,7 @@ namespace Frida.Fruity {
polled_usb_timer = null;
}

lock (pending_usb_ops) {
lock (state) {
if (pending_usb_ops.is_empty)
state = STOPPING;
}
Expand Down Expand Up @@ -1048,16 +1052,36 @@ namespace Frida.Fruity {
polled_usb_devices = current_devices;
}

private UsbOperation allocate_usb_operation () {
private UsbOperation allocate_usb_operation () throws Error {
var op = new PendingUsbOperation (this);
lock (pending_usb_ops)
pending_usb_ops.add (op);

bool added = false;
lock (state) {
switch (state) {
case CREATED:
break;
case STARTING:
case STARTED:
pending_usb_ops.add (op);
added = true;
break;
case FLUSHING:
case STOPPING:
case STOPPED:
break;
}
}

if (!added)
throw new Error.INVALID_OPERATION ("Unable to allocate USB operation in the current state");

return op;
}

private void on_usb_operation_complete (PendingUsbOperation op) {
lock (pending_usb_ops)
lock (state)
pending_usb_ops.remove (op);

usb_context.interrupt_event_handler ();
}

Expand Down
2 changes: 1 addition & 1 deletion src/fruity/usb.vala
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ namespace Frida.Fruity {
}

internal interface UsbDeviceBackend : Object {
public abstract UsbOperation allocate_usb_operation ();
public abstract UsbOperation allocate_usb_operation () throws Error;
}

internal interface UsbOperation : Object {
Expand Down

0 comments on commit ec58296

Please sign in to comment.