ReadBytesAsync sporadically hangs on reading 6 MB message on iOS
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 6.1k
- Forks
- 1.7k
- PR merge metrics
- No merged PRs in 30d
Description
The ReadBytesAsync function for messages greater than 2^16 in length sometimes fails on iOS while trying to read from the socket stream. For example, I sent a 6 MB message from our server down to our iOS client. The server reports that all of the data was sent, but it is never read from the read function. I edited the code to add some print statements:
internal static void ReadBytesAsync (
this Stream stream,
long length,
int bufferLength,
Action<byte[]> completed,
Action<Exception> error
)
{
var dest = new MemoryStream ();
var buff = new byte[bufferLength];
var retry = 0;
Action<long> read = null;
read =
len => {
if (len < bufferLength)
bufferLength = (int) len;
stream.BeginRead (
buff,
0,
bufferLength,
ar => {
try {
var nread = stream.EndRead (ar);
Console.WriteLine ("LENGTH REMAINING: " + len);
Console.WriteLine ("READING # PAYLOAD BYTES: " + nread);
if (nread <= 0) {
if (retry < _retry) {
Console.WriteLine ("RETRY");
retry++;
read (len);
return;
}
if (completed != null) {
dest.Close ();
completed (dest.ToArray ());
}
dest.Dispose ();
return;
}
dest.Write (buff, 0, nread);
if (nread == len) {
if (completed != null) {
dest.Close ();
completed (dest.ToArray ());
}
dest.Dispose ();
return;
}
retry = 0;
read (len - nread);
}
catch (Exception ex) {
Console.WriteLine (ex);
dest.Dispose ();
if (error != null)
error (ex);
}
},
null
);
};
try {
read (length);
}
catch (Exception ex) {
dest.Dispose ();
if (error != null)
error (ex);
}
}
"RETRY" is never printed, no exceptions are thrown and the reading from the stream stopped in the middle of the message:
...
LENGTH REMAINING: 4816503
READING # PAYLOAD BYTES: 1024
LENGTH REMAINING: 4815479
READING # PAYLOAD BYTES: 1024
LENGTH REMAINING: 4814455
READING # PAYLOAD BYTES: 1024
LENGTH REMAINING: 4813431
READING # PAYLOAD BYTES: 1024
LENGTH REMAINING: 4812407
READING # PAYLOAD BYTES: 1024
LENGTH REMAINING: 4811383
READING # PAYLOAD BYTES: 1024
As far as I can tell the code seems to be correct, however. I'm not sure if this is an issue with BeginRead or what. It seems that the callback passed into BeginRead is never called.
Also just out of curiosity, why is the buffer size 1024 rather than 2^16? Is there a point to using this function over the other considering it's all being buffered in memory and then scooped into an array by the dest memory stream?
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by inspecting the ReadBytesAsync implementation shown in the issue and the BeginRead/EndRead callback path used for iOS streams. Reproduce a message larger than 2^16 bytes, determine why the callback stops after partial reads, and verify that the complete payload is delivered without hanging; also document whether the 1024-byte buffer is intentional.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100