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

Thread Safety #37

Open
marcFriesen opened this issue Apr 11, 2022 · 3 comments
Open

Thread Safety #37

marcFriesen opened this issue Apr 11, 2022 · 3 comments

Comments

@marcFriesen
Copy link

I am having an issue where the TCPIP task is overwriting other tasks stacks. The function static uint16_t _TCPSocketTxFreeSize(TCB_STUB* pSkt) is returning a size of 0xFFFF due to the function getting preempted after the second if statement, but before it returns the calculated size. At the time of comparing the head to the tail, the head is less, after the if is skipped the head and tail are equal. Here is the function body:

static uint16_t _TCPSocketTxFreeSize(TCB_STUB* pSkt)
{
    // Unconnected sockets shouldn't be transmitting anything.
    if(!( (pSkt->smState == TCPIP_TCP_STATE_ESTABLISHED) || (pSkt->smState == TCPIP_TCP_STATE_CLOSE_WAIT) ))
    {
        return 0;
    }

	
    // Calculate the free space in this socket's TX FIFO	
    if(pSkt->txHead >= pSkt->txTail)
    {
        return (pSkt->txEnd - pSkt->txStart - 1) - (pSkt->txHead - pSkt->txTail);
    }

    return pSkt->txTail - pSkt->txHead - 1;
}

Is thought the library was thread-safe, is there something else I need to add? I've configured the library to use thread-safe malloc/free provided by FreeRTOS, as well as adding a thread-safe calloc.

@adrian-aur
Copy link
Collaborator

adrian-aur commented Apr 11, 2022

Are you trying to use the same socket from multiple threads?
Please see the remarks in the tcp.h:

"Sockets and user threads protection
For efficiency reasons, there is NO PROTECTION for each individual API call
except to Open and Close sockets!
What it means is that:
- the user application should close all its sockets before issuing
a stack/if down command
The stack manager takes care of the internally used sockets

        - A socket can NOT be used concurrently from multiple threads!
          It's ok to pass a socket from one thread to another as long as
          there's is no access from more than one thread at a time"

Please let me know if this answers your issue.

@marcFriesen
Copy link
Author

No, the socket is opened and used by one thread only. I have a while loop that is writing a buffer (~4K) until all bytes have been sent. The TCPIP task preempts this task and seems to change the head/tail pointers while we are also trying to send more data. I've added a workaround to delay 5ms in the while loop between successive reads/writes of TCP which seems to avoid this race condition.

@adrian-aur
Copy link
Collaborator

It'd be helpful if you could identify the part of the code that overwrites those head/tail pointers.
Are you sure it's the TCP/IP stack? Maybe you could increase the stack size for some of the threads in there.
I think it's important to understand if this is a buffer overwrite or simply a 'legitimate' access made by the stack, but without the necessary multi-thread protection.

Also, would it be possible to send to me a simplified version of your code that exposes this behavior?
I'll try to dig into it and see what happens.
But it may take a while, it could be not obvious how to catch this kind of behavior.

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

No branches or pull requests

2 participants