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

Remove blocking IO #1277

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Remove blocking IO #1277

wants to merge 1 commit into from

Conversation

irdkwmnsb
Copy link

Consider side A to be the client (program ran on a host machine), B to be the server (ios device) and P to be python process.

When we have B streaming the data to A over P and A doesn't want to read the packets from it's socket - the kernel will keep them in a buffer. And when it fills up, next time P receives a packet from B it will block on line 122 because the buffer of socket P->A is full. And pymobiledevice3 hangs altogether and doesn't receive new connections.

While this change breaks some use cases I think it is generally better to not block io operations if the kernel buffer is full.

@doronz88
Copy link
Owner

Doesn't this just pass the blocking part into the sender endpoint instead of the receiver?

@doronz88
Copy link
Owner

Also, this is from python's documentation:

Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Unlike send(), this method continues to send data from bytes until either all data has been sent or an error occurs. None is returned on success. On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent.

As I understand this, the sendall() is already blocking. How does this make any difference?

@irdkwmnsb
Copy link
Author

Also, this is from python's documentation:

Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Unlike send(), this method continues to send data from bytes until either all data has been sent or an error occurs. None is returned on success. On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent.

As I understand this, the sendall() is already blocking. How does this make any difference?

As per the documentation many details are system-dependent.
On linux and Darwin the use case I described definitely blocks the operation and no more sockets are being opened or data is being sent until the client socket is being read from.

@irdkwmnsb
Copy link
Author

Also, this is from python's documentation:

Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Unlike send(), this method continues to send data from bytes until either all data has been sent or an error occurs. None is returned on success. On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent.

As I understand this, the sendall() is already blocking. How does this make any difference?

There is no behavioural difference in send and sendall when it comes to blocking and waiting for kernel response.
The only difference is that sendall will try to send data until all data is sent. Since POSIX's write gives no guarantee to how many bytes will be definitely sent to the socket, sendall will repeatedly send data until all is written.
See https://stackoverflow.com/a/34252690

@irdkwmnsb
Copy link
Author

Doesn't this just pass the blocking part into the sender endpoint instead of the receiver?

And no, the connection will be closed upon a read/write error which will occur if the buffer is full and no data is being read.

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.

2 participants