msquic icon indicating copy to clipboard operation
msquic copied to clipboard

StreamSend method hangs when called in an infinite loop

Open UyraIV opened this issue 1 year ago • 7 comments

Describe the bug

A crash occurs if StreamSend called in an infinite loop.

Affected OS

  • [ ] Windows
  • [X] Linux
  • [ ] macOS
  • [ ] Other (specify below)

Additional OS information

Ubuntu 22.04.3 LTS

MsQuic version

main

Steps taken to reproduce bug

  1. Run
    uint64_t i = 0;
    char numStr[100];
    while (TRUE)
    {
        QUIC_BUFFER *msg = (QUIC_BUFFER *)malloc(sizeof(QUIC_BUFFER) + sizeof(i));
        msg->Length = sizeof(i);
        sprintf(numStr, "%ld\n", i);
        msg->Buffer = numStr;
        MsQuic->StreamSend(Stream, msg, 1, flags, msg);
        i++;
    }
  1. View output on the server
  2. See the broken order of numbers, then the slowdown of incoming messages to the server, and finally the connection is broken.

Expected behavior

  1. Run
    uint64_t i = 0;
    char numStr[100];
    while (TRUE)
    {
        QUIC_BUFFER *msg = (QUIC_BUFFER *)malloc(sizeof(QUIC_BUFFER) + sizeof(i));
        msg->Length = sizeof(i);
        sprintf(numStr, "%ld\n", i);
        msg->Buffer = numStr;
        MsQuic->StreamSend(Stream, msg, 1, flags, msg);
        usleep(1);
        i++;
    }
  1. View output on the server
  2. See the correct order of numbers.

350543

350544

350545

350546

350547

350548

350549

350550

350551

350552

350553

350554

350555

350556

350557

350558

350559

350560

350561


Actual outcome

249944
249944
249944
249944
249944
249944
249944
249944
249944
249944
249944
249944
249944
249944
249944
249944
249944
249945
249945
249945
249945
249945
249945
249945
249945
249945
249945
249945
249945
24994
[conn][0x7fef28061120] Shut down by transport, 0x6e

Additional details

No response

UyraIV avatar Mar 07 '24 08:03 UyraIV

All your sends point to the same memory, 'numStr', for which you continue to change. Send just queues to the MsQuic thread and immediately returns. You cannot reuse that memory until you get a send completion.

nibanks avatar Mar 07 '24 12:03 nibanks

Yes, memory, I apologize for such trivial mistakes, I recently got acquainted with C. It helped with the order of numbers, but the main problem remained. 1-2 packets of 10k-20k messages are sent to the server. After that, the connection is interrupted.

UyraIV avatar Mar 07 '24 12:03 UyraIV

That error, 0x6e, refers to QUIC_STATUS_CONNECTION_TIMEOUT, which indicates the connection is timing out (i.e. getting 'disconnected'). Are you doing printf, or some other blocking call, on the MsQuic callback? My guess is that you are delaying the peer from responding long enough that the connection dies.

nibanks avatar Mar 07 '24 12:03 nibanks

Disabled everything that could block in callbacks (except error output), the error changes between 0x6e and 0x3e.

UyraIV avatar Mar 07 '24 13:03 UyraIV

That error is QUIC_STATUS_CONNECTION_IDLE, which means the connection is torn down because it's been unused for too long. So it looks like you fixed it! 😄

nibanks avatar Mar 07 '24 14:03 nibanks

It would be nice, but there is a StreamSend call in an infinite loop... Therefore, in theory, the connection should not be idle.

UyraIV avatar Mar 07 '24 16:03 UyraIV

If you continue to call send, but the connection says idle, that likely means flow control kicked in, blocking further sends. This can happen if you're not draining the data in the receive callback. I recommend you grab some logs and take a look.

nibanks avatar Mar 07 '24 16:03 nibanks