Skip to content

[BUG] srt_listen() wrongly reports SRT_EUNBOUNDSOCK if socket is closed during the call #3297

@fchasse-rd

Description

@fchasse-rd

Describe the bug
While testing for concurrent calls to srt_listen() and srt_close(), I got a case where srt_listen() will report SRT_EUNBOUNDSOCK if srt_close() is called at a specific time during the srt_listen() call, even though the socket was successfully bound before entering.

Looking at the code, it seems to come from this snippet in srt::CUDTUnited::listen:
https://github.com/Haivision/srt/blob/master/srtcore/api.cpp#L1151C1-L1153C57

This is similar to #3289 (comment) where the code should instead check for if (int(s->m_Status) >= SRTS_BROKEN), as per the fix.

To Reproduce

#include <assert.h>
#include <future>
#include <iostream>
#include <srt/srt.h>

int32_t test_srt_listen_abort()
{
    SRT_SOCKSTATUS state{};

    [[maybe_unused]]
    int err = srt_startup();
    assert(err == 0);

    // Set up as rendezvous, blocking mode (default).
    auto socket = srt_create_socket();

    // Bind to localhost.
    {
        sockaddr_in local{};
        local.sin_family = AF_INET;
        local.sin_port   = htons(9'000);
        inet_pton(AF_INET, "0.0.0.0", &local.sin_addr);

        err = srt_bind(socket, reinterpret_cast<sockaddr*>(&local), sizeof(local));
        assert(err == 0);
        state = srt_getsockstate(socket);
        assert(SRTS_OPENED == state);
    }
    std::cout << "Socket bound to localhost. Socket state = " << state << std::endl;

    // start listening in one thread, close the socket in the other.
    auto listenFuture = std::async([&]() { return srt_listen(socket, 1) ? srt_getlasterror(nullptr) : 0; });
    auto closeFuture  = std::async([&]() { return srt_close(socket) ? srt_getlasterror(nullptr) : 0; });

    auto listenResult = listenFuture.get();
    auto closeResult  = closeFuture.get();

    state = srt_getsockstate(socket);
    std::cout << "Completed." << std::endl;
    std::cout << "    Socket state  = " << state << std::endl;
    std::cout << "    Close result  = " << closeResult << std::endl;
    std::cout << "    Listen result = " << listenResult << std::endl;

    if ((listenResult != SRT_SUCCESS && listenResult != SRT_EINVSOCK))
    {
        std::cerr << "Unexpected listen result: " << listenResult << std::endl;
    }

    err = srt_cleanup();
    assert(err == 0);

    return listenResult;
}

Expected behavior
srt_listen() should return SRT_ESCLOSED if the socket is closed during the call.

Desktop (please provide the following information):

  • OS: Ubuntu 24.04 (x64)
  • SRT Version / commit ID: v1.5.5-rc.1
  • Build profile: Release

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type: BugIndicates an unexpected problem or unintended behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions