Skip to content

[BUG] FreeRTOS_accept() returns no connection while an established child is still pending #1364

Description

@nding0405

Describe the bug

A listening socket can have multiple pending established child connections waiting for FreeRTOS_accept().

If the child currently referenced by the listener (the first pending child connection) is reset before it is accepted, FreeRTOS clears the reference but does not select another established child. FreeRTOS_accept() then returns NULL, even though another valid child is still in eESTABLISHED.

If no new connection arrives, the remaining child will not be rescanned. The connection can remain stuck, occupy a listener capacity slot, and leave the client blocked.

Target

  • Development board: QEMU MPS2, using the official FreeRTOS_Plus_TCP_Echo_Qemu_mps2 demo
  • Instruction Set Architecture: 32-bit Armv7-M, Cortex-M3, Thumb-2, little-endian, no hardware FPU (-machine mps2-an385 -cpu cortex-m3; compiler flags -mcpu=cortex-m3 -mthumb)
  • IDE and version: None. command-line build using GNU Make
  • Toolchain and version: Arm GNU Toolchain 15.3.Rel1: arm-none-eabi-gcc 15.3.1 20260627 (Build arm-15.149)

Host

  • Host OS: macOS
  • Version: macOS 26.5.1 (Build 25F80)

To Reproduce

  1. Use the official FreeRTOS_Plus_TCP_Echo_Qemu_mps2 demo.
  2. Replace the demo TCP task with the attached poc.c.
  3. Use the attached FreeRTOSIPConfig.h.
  4. Run:
make reproduce

The client performs these steps:

  1. Client A connects.
  2. Client B connects.
  3. Client A closes with an RST.
  4. Client B sends one byte and waits for a reply.
  5. The server calls non-blocking FreeRTOS_accept().

Relevant output:

A and B connected; B source port: 60069

A reset; B sent one byte and is now blocked in recv()

Socket 12345 -> [10.0.2.2]:60068 State eSYN_RECEIVED->eESTABLISHED
Socket 12345 -> [10.0.2.2]:60069 State eSYN_RECEIVED->eESTABLISHED
Socket 12345 -> [10.0.2.2]:60068 State eESTABLISHED->eCLOSED

POC_RESULT: BUG: accept returned no connection

TCP 12345 0ip       :    0 0/0 eTCP_LISTEN  10000     0 1/2
TCP 12345 a000202ip :60069 1/0 eESTABLISHED  5658 11648

POC_PROOF: client B is still blocked after accept returned NULL

The output shows that:

  • A and B both reached eESTABLISHED.
  • A, using source port 60068, was reset and closed.
  • FreeRTOS_accept() returned no connection.
  • B, using source port 60069, was still in eESTABLISHED.
  • The listener still reported one child in its status report: 1/2.

Therefore, the server still has a valid pending child, but the application cannot obtain it through FreeRTOS_accept().

Expected behavior

After A is reset, FreeRTOS_accept() should find and return B. Removing one pending child should not make another established child unreachable.

Screenshots

Not applicable.

Additional context

Server side reproducer: poc.c
Client side reproducer: client.py

The listener appears to keep only one pending child in pxPeerSocket. When that child is removed, the pointer is cleared, but another established child is not filled into the slot.

A possible fix:

  1. When the child pointed by listener->pxPeerSocket is removed, clear the closing child’s accept flags.
  2. Rescan the listener’s remaining children.
  3. If another established child is ready, assign it to listener->pxPeerSocket.
  4. Set the accept event and wake any task waiting in FreeRTOS_accept().

The closing child’s flags should be cleared before the rescan so that the closing child cannot be selected again.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions