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

[core] Fixed thread safety using WSAOVERLAPPED in WSASendTo(#2838). #2861

Closed
wants to merge 2 commits into from

Conversation

mGaosi
Copy link
Contributor

@mGaosi mGaosi commented Jan 22, 2024

The lpOverlapped parameter must be valid for the duration of the overlapped operation. If multiple I/O operations are simultaneously outstanding, each must reference a separate WSAOVERLAPPED structure.

This reverts commit b1c0be2.

resolves #973 #2632 #2834 #2838

@maxsharabayko maxsharabayko added this to the v1.5.4 milestone Jan 22, 2024
@maxsharabayko maxsharabayko added Type: Bug Indicates an unexpected problem or unintended behavior [core] Area: Changes in SRT library core labels Jan 22, 2024
@maxsharabayko
Copy link
Collaborator

The hEvent was added in PR #2834 to be used in WSASendForMultipleEvents.
The previous version used in SRT v1.5.3 was using directly WSAGetOverlappedResul with an infinite wait which on a file transmission over a local area network resulted in an infinite hang up.
This PR restores this behavior, I believe.

@mGaosi
Copy link
Contributor Author

mGaosi commented Jan 22, 2024

I am currently unable to reproduce issue of PR#2834 in our case.

Maybe:
image
These small differences may also be one of the reasons.

WSAWaitForMultipleEvents(..., 100 /*ms*/, ...); It looks more secure. But if the WSAOVERLAPPED object(or some param) is using in WSASendTo ...

@maxsharabayko
Copy link
Collaborator

The hang up is reproducible when transferring files from a Windows machine using srt-xtransmit. I can re-check with the event handle being created. But I assumed it does not have to be created given it is not used, as there is noone waiting on it.

@mGaosi
Copy link
Contributor Author

mGaosi commented Jan 24, 2024

I have another idea:

    DWORD size = (DWORD)(CPacket::HDR_SIZE + packet.getLength());
    int addrsize = addr.size();
    int res = 0;
    while (true)
    {
        res = ::WSASendTo(m_iSocket, (LPWSABUF)packet.m_PacketVector, 2, &size, 0, addr.get(), addrsize, NULL, NULL);
        if (res == 0)
        {
            res = size;
            break;
        }
        else if (WSAGetLastError() == WSAEWOULDBLOCK)
        {
            res = ::WSAEventSelect(m_iSocket, m_event, FD_READ | FD_WRITE);
            if (res != 0)
            {
                LOGC(kslog.Warn, log << "CChannel::sendto WSAEventSelect failed " << NET_ERROR);
                break;
            }
        }
        else
        {
            break;
        }
    }

@maxsharabayko
Copy link
Collaborator

@mGaosi I am testing your current proposal (this PR). Surprisingly it does not hang up. Looks like the problem was indeed in the handle that needed to be assigned. I'm still running some more iterations to ensure, but about 6 runs went without a single hang-up already.

srtcore/channel.cpp Outdated Show resolved Hide resolved
srtcore/channel.cpp Outdated Show resolved Hide resolved
#if HAVE_CXX11
thread_local WSAEventRef lEvent;
#else
WSAEventRef lEvent;
Copy link
Collaborator

@ethouris ethouris Jan 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we keep the wrong solution in case of non-C++11 build?

If we state that the Windows version can only be compiled with C++11, and this feature is exclusively for Windows, then we don't need any alternative here.

If we allow C++03 with POSIX threads version compiled on Windows, then this alternative should contain a special type wrapper that would use a boolean marker operated with pthread_once.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not completely wrong, it just creates and deletes a local object on each call for non-C++11 Windows builds.
This would also be the case for the minGW build.
Using pthread_once would be of course better.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, the situation is this: we can just as well disable "old" builds on MICROSOFT (that is, Windows with MSVC), but there is still possible MinGW with C++03, the possibility to compile successfully with C++11 (and C++11 sync) exists for MinGW, but this doesn't always work.

Still, I don't get why you apply thread_local onto a local variable.

Copy link
Collaborator

@maxsharabayko maxsharabayko Apr 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thread_local implies static when static is omitted. So it is thread_local static.

…#2838).

The lpOverlapped parameter must be valid for the duration of the overlapped operation. If multiple I/O operations are simultaneously outstanding, each must reference a separate WSAOVERLAPPED structure.

This reverts commit b1c0be2.

resolves Haivision#973 Haivision#2632 Haivision#2834 Haivision#2838
Copy link
Collaborator

@maxsharabayko maxsharabayko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MinGW build still fails.

CMakeLists.txt Outdated Show resolved Hide resolved
Comment on lines 802 to 804
#if ENABLE_CXX11
thread_local WSAEventRef lEvent;
#else
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this?

Suggested change
#if ENABLE_CXX11
thread_local WSAEventRef lEvent;
#else
#ifdef ENABLE_STDCXX_SYNC
thread_local WSAEventRef lEvent;
#else

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't work, too, because the command line is not using C++11.

ENABLE macros configure what you want to have compiled, not what is possible to be compiled in the current env.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HAVE_FULL_CXX11 ?

srtcore/channel.cpp Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[core] Area: Changes in SRT library core Type: Bug Indicates an unexpected problem or unintended behavior
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG] Check return of a non-blocking UDP send
3 participants