aioftp icon indicating copy to clipboard operation
aioftp copied to clipboard

Deadlock upon calling `await client.abort()`

Open michaelwillis opened this issue 1 year ago • 5 comments

I'm trying to implement abort download as described in Advanced download and upload, abort, restart. Following the example, I find that await client.abort() deadlocks, but if my code first calls stream.close(), then it can call await client.abort() without deadlock. Are these two lines mixed up in the example?

michaelwillis avatar May 23 '23 13:05 michaelwillis

How your code looks like? Did you read the warning part? https://aioftp.readthedocs.io/client_tutorial.html#id2

pohmelie avatar May 23 '23 15:05 pohmelie

Yes, I read the warning and tried to follow it. Here is my code, which is working now that it calls stream.close() and await client.abort() in reverse order from that recommended by the warning:

async with aioftp.Client.context(HOST, user=USER, password=PASSWORD) as client:
    # See note about how to abort streaming download without causing deadlock:
    # https://aioftp.readthedocs.io/client_tutorial.html#advanced-download-and-upload-abort-restart
    stream = await client.download_stream(filename)
    completed = False
    try:
        # stream_process_lines() returns false if download should be aborted
        completed = await stream_process_lines(stream)
        if completed:
            await stream.finish()
    finally:
        # Need to abort download if either stream_process_lines() returned False or an exception was raised
        if not completed:
            stream.close()
            await client.abort()

michaelwillis avatar May 23 '23 16:05 michaelwillis

Can you provide some log messages? So I can release where stuck is.

pohmelie avatar May 24 '23 12:05 pohmelie

Hmm, I rewrote the code as follows and it gives me almost no problems:

try:
    async with aioftp.Client.context(HOST, user=USER, password=PASSWORD) as client:
        async with client.download_stream(filename) as stream:
            await stream_process_lines(stream)
except Exception as e:
    log.error("Error processing file: %s, %s" % filename, e)

This code always exits, never deadlocks. If stream_process_lines(stream) either raises an exception or returns early without consuming the entire stream, then the end of the log statement says Waiting for ('2xx',) but got 450 [' Transfer aborted forcefully by client.'], which seems fine to me.

michaelwillis avatar May 24 '23 16:05 michaelwillis

But issue exists. Maybe you can replicate the issue and provide some logs. Since I still have no clue about reasons for such behavior.

pohmelie avatar May 25 '23 13:05 pohmelie