-
-
Notifications
You must be signed in to change notification settings - Fork 199
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
SocketWrapper MbedClient debugging readSocket #912
base: main
Are you sure you want to change the base?
Conversation
Hi @JAndrassy, I agree with the changes you made for point 1. |
@andreagilardoni so should we add everywhere to
I didn't look in the source but I think the unconnected socket still counts as used one from socket-max |
I think the only method missing the check for The changes on lines 123:124 are necessary. I only need to understand why you performed changes on |
|
00b5add
to
a5fc13f
Compare
changes:
|
444339a
to
00bc011
Compare
@JAndrassy after looking at that everything seems ok, I need to try to run some examples and then I think we can merge this PR. I like how you reorganized the thread function, thanks for your contribution! |
00bc011
to
a40c63f
Compare
There is one more problem with the readSocket thread, but if I patch the solution in, it screams for a rewrite of the whole inner loop. the problem is that on err < 0 the thread ends. it can be just that the peer closed the connection. on a new |
I quickly tested this PR and I don't see any issues with this. About the other issue you are describing, what |
sorry ret not err
|
If the peer closed the connection than, I think, it is expected that the socket has to be closed and needs to be restarted. In connect I can see that this check is performed ArduinoCore-mbed/libraries/SocketWrapper/src/MbedClient.cpp Lines 84 to 89 in 2ece915
Did I get your point? |
then it is ok |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to analyse and test the proposed changes and I have a few comments (I hope you can find them meaningful).
One thing I found really confusing is the use of the _status
flag which is set / reset in a lot of different places (and this make difficult to understand the underling logic).
In the readSocket()
thread is appears that is not really necessary to set _status=true
at the end of each innermost do-while
cicle.
There is no need to set _status=true
after the call of the configureSocket()
function since is the configureSocket()
function itself sets _status=true;
. This happens twice: in the connect()
and the connectSSL()
function.
As additional simplification I would reset _status
to false at the beginning of those 2 functions (if all goes well the configureSocket()
function will set it to true
and in case of problem it will remain set to false
removing the need of setting if to false
in case of errors). This removes the need to set _status
to false in case of problem and ensure it is false if something wrong happened.
About the mutex lock/unlock in the write()
function, my understanding is that the mutex is used to prevent access to the rxBuffer
from different threads, so it appears to be not necessary here. One point that is certainly wrong is that the changes removed the check about the sock
pointer: it is necessary to reintroduce here the check
if (sock == nullptr) {
return 0;
}
this is very important because a user can call write()
with an invalid sock
and this would crash the program.
Since the mutex is used to prevent "common" access to rxBuffer
I noticed that the peek()
function that uses rxBuffer
is unprotected: I would add the mutex lock/unlock mechanism to the peek()
function.
A possible improvement is related to the setSocket()
function: this function is called when client is create by a server. However the server allocates a Socket
only if there is an incoming request, in case no request is made the server will always call setSocket(nullptr)
(please check the EthernetServer::available()
function in the EthernetServer.cpp file and verify if my understanding is correct).
In case like this it is probably pointless to call configureSocket()
so I would add a check and execute the body of the function only if _sock
is different from nullptr.
My last remark is more a doubt: in the connect()
and connectSSL()
function almost at the end of the function in case ret
is not 1 it has been added the statement sock->close()
, but this only closes the Socket
. Would not be better to call directly the MbedClient
stop()
function? This would reset all the variables held by the client and not only "close the socket".
I avoid doing unnecessary changes in my PR. Where would I stop if I begin to cleanup the code. So I don't even start. So the superfluous The readSocket() function runs in a separate thread so it can't switch _status to false if it isn't definitive. I can remove the lock from write. (btw if socket is null, then mutex is null too) yes. peek() needs the lock. I add it.
as I understand it, the idea is that the socket can be reused for next try to connect, that is why it is not deleted. calling stop() would delete it. all other fields are not initialized because configureSocket didn't run |
a40c63f
to
dbe0b07
Compare
dbe0b07
to
3428d75
Compare
I made these changes ^^^ |
Maybe this patch could help fixing #937 ? |
@@ -22,28 +22,30 @@ void arduino::MbedClient::readSocket() { | |||
int ret = NSAPI_ERROR_WOULD_BLOCK; | |||
do { | |||
mutex->lock(); | |||
if (sock != nullptr && rxBuffer.availableForStore() == 0) { | |||
if (sock == nullptr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this subject to the same issues as "Another racy example" here: https://queue.acm.org/detail.cfm?id=2088916? sock is loop invariant but changed in another thread. mutex is the same isn't it?
In
connect
we have to delete the socket object, because all other functions test it for null and then use mutex which is null, because configureSocket was not invoked. And there are too few sockets in total.In
readSocket
the condition of the inner loop was always true and the inner loop never exited to wait for event or timeout on event. The inner loop only paused for yield(). With the PR if no data are available the inner loop doesbreak
to outer loop where the thread waits for event or timeout.3) I think we have to do mutex inwrite
too