-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Add std::nothrow and null checks to netsocket lib #14223
Conversation
@0xc0170 I had a question: I changed a return value from |
@pea-pod, thank you for your changes. |
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.
Thanks for the submission @pea-pod .
I think that is a good change but any change to an API signature is a breaking change.
For example, the following code will stop to work:
void sink(void (NetworkInterface::*)(mbed::Callback<void(nsapi_event_t, intptr_t)>));
void foo() {
// Error, the signature was void(mbed::Callback<void(nsapi_event_t, intptr_t)>)
// and is now nsapi_error_t(mbed::Callback<void(nsapi_event_t, intptr_t)>)
sink(&NetworkInterface::add_event_listener);
}
These type of code are rare but will break with the proposed change.
There is also a change from a behavior perspective. The pointers were not unchecked; they were simply not used because the system abort the execution of the program if new
returns a nullptr.
To avoid backward compatibility hell, I'd suggest adding a compilation flag that allows the application to select the new behavior and signature. The void signature can exhibit include a deprecation notice explaining that it will be removed and which compiler flag should be enabled to make it go away.
Internally, the implementation can retain uses of std::nothrow
and call mbed_error
to replicate the old behavior or return the error for the new behavior.
When a major release is made, we can remove the compilation flag and associated wards in the code.
query->socket_cb_data = new (std::nothrow) SOCKET_CB_DATA; | ||
if (!query->socket_cb_data) { | ||
nsapi_dns_query_async_resp(query, NSAPI_ERROR_NO_MEMORY, NULL); | ||
return; |
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.
Why not return an error ?
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.
While I won't pretend I understand this portion too much, the function signature here is static void nsapi_dns_query_async_create(void *ptr)
. This function is a helper for the async DNS query, and I believe the nsapi_dns_query_async_resp
call takes care of the error return call.
I did not believe I looked hard enough, however, because I believe that I did not clean up the UDP socket and the appropriate call to the stack created earlier in the same function call.
I will admit that I never really conceived of this level of indirection. Regarding your example specifically, is this actually possible as is? I am not trying to nitpick, but don't you also need need a reference to the instance? Assuming that change went into your example, would it change anything? I think not, but I am not nearly as knowledgeable here.
I understand what you are getting at in a low level, but I would not consider the device trapping due to attempting to set values at location
I agree with the idea compilation flags for the |
Of course, the code I provided is possible as is. You can see the compilation fail here: https://godbolt.org/z/j3Gb64
I agree with you and that is why I think that PR is important, however I wanted to point out that the system was not crashing due to an access to a nullptr. It crashes in the allocation routine which is - in a way - less damaging especially on system where That's something we lose in the new implementation of |
I apologize. I was not very clear in my response. First, what I meant with the question about it working was simply that your example seemed to lack a context pointer in the Second, I do agree with adding the compiler checks to the My final point of clarification is how to deal with the other changes I made. I am not sure if you were saying that all changes should have the conditional compilation, or just the |
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.
To move this PR forward I think the following points could be improved:
add_event_listener
should have different signatures based on a compile time parameter. This will preserve backward compatibility.TLSSocketWrapper::print_mbedtls_error
can use a buffer allocated on the stack. It is just 128 bytes large.- The change in
nsapi_dns_query_async_create
does not require to forward the error in a return statement as the call tonsapi_dns_query_async_resp
does it. However, the socket created above in the function must be deleted.
@@ -427,7 +435,11 @@ void TLSSocketWrapper::print_mbedtls_error(MBED_UNUSED const char *name, MBED_UN | |||
{ | |||
// Avoid pulling in mbedtls_strerror when trace is not enabled | |||
#if defined FEA_TRACE_SUPPORT && defined MBEDTLS_ERROR_C | |||
char *buf = new char[128]; | |||
char *buf = new (std::nothrow) char[128]; |
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.
This can be a buffer on the stack: char buf[128]
. We don't need memory allocation for 128 bytes.
2af930f
to
1a3d730
Compare
1a3d730
to
04f15a3
Compare
After the updates, I now fail spell checking in several locations, but none of the words were misspelled. I even put one instance in I do not know how to proceed forward at this point. |
@0xc0170 What's the error here ? Is it the use of |
Per the build error on the CI:
It does choke on "std::nothrow" but it also fails at several places that I wrote "configure" or "configuration" (etc.) instead of "conf". |
This pull request has automatically been marked as stale because it has had no recent activity. @pea-pod, please carry out any necessary work to get the changes merged. Thank you for your contributions. |
I have changed the PR to reflect the return code change, but given that I have |
@0xc0170 Do you now have time to look at the CI error? |
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.
These 2 should fix the Travis failures.
Sorry for the delay
* Application may only use attach() or add_event_listener() interface. Mixing usage | ||
* of both leads to undefined behavior. | ||
* | ||
* @warning This version of the function does not use the `std::nothrow` feature. Subsequently, |
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.
To fix the spellchecker:
add nothrow to mbed-os/tools/test/travis-ci/doxy-spellchecker/ignore.en.pws
* @warning This version of the function does not use the `std::nothrow` feature. Subsequently, | ||
* the function may fail to allocate memory and cause a system error. To use the new | ||
* version with the changes, set "nsapi.add-event-listener-return-change": 1 in the | ||
* target overrides section in your mbed_app.conf file. |
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.
this should be mbed_app.json
(not conf)
@0xc0170 Thank you. I should be able to get to these changes this week. I believe that since my changes are guarded with This isn't the right place for discussion, but is someone collecting a punch list of changes that should go into a 7.0? I would not mind even starting a PR that would get shelved, but I think it would be in danger of becoming unable to merge at some point. A list would be an compromise between no changes and a shelved PR. |
Hi @pea-pod, Is the intention here that the API consumer be able to handle the OOM condition, or is there just a concern that the allocation would silently return I can pick this PR up and get it merged if there is a desire to return the OOM code from the API so the consumer can handle it somehow (e.g. delete some cached objects) but if it is just to prevent silent failures, then calling the |
I'll close this as it has not been updated (as proposed the new PR can be created once we get more details as requested above) |
…bed#14210) Incorporates PR ARMmbed#14223 + changes required for spellchecker
…bed#14210) Incorporates PR ARMmbed#14223 + changes required for spellchecker
Summary of changes
This changes adds
std::nowthrow
and the checks for allocation failure to all places in thenetsocket
portion that lacked it. This change addresses #14210.Impact of changes
add_event_listener
inNetworkInterface
now returns an error if the method fails. Previous attempts to add the event listener would attempt to use an unchecked standard dynamically allocatedns_list_*
item.In other cases, the dynamically allocated items will now be checked, and if unsuccessful, will return after cleaning up any outstanding issues.
TCPSocket::accept
will now check that its own internally allocatednew TCPSocket
call will succeed, and if not, will clean up the stack resources. This should help when memory is low but an incoming connection requests a connection when theTCPSocket
is listening.Migration actions required
As
new
calls are now handled, code that did not check against this failure may now check for failure and handle it at the application layer.add_event_listener
now returnsnsapi_error_t
instead ofvoid
. The two return values possible areNSAPI_ERROR_OK
andNSAPI_ERROR_NO_MEMORY
in the case of memory allocation failure.Documentation
NetworkInterface.h
now has changes to theadd_event_listener
method. This method will now returnnsapi_error_t
instead ofvoid
. The docstring for the interface has been updated.Pull request type
Test results
Reviewers