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

refactor: add gsl::not_null to get compile time / run time pointer guarantees #5595

Merged

Conversation

PastaPastaPasta
Copy link
Member

Issue being fixed or feature implemented

Current implementation relies either on asserts or sometimes checks then returning a special value; In the case of asserts (or no assert where we use the value without checks) it'd be better to make it explicit to function caller that the ptr must be not_null; otherwise gsl::not_null will call terminate.

See https://github.com/microsoft/GSL/blob/main/docs/headers.md#user-content-H-pointers-not_null and https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-nullptr

I'm interested in a conceptual review; specifically on if this is beneficial over just converting these ptrs to be a reference?

What was done?

Partial implementation on using gsl::not_null in dash code

How Has This Been Tested?

Building

Breaking Changes

None

Checklist:

Go over all the following points, and put an x in all the boxes that apply.

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone (for repository code-owners and collaborators only)

@PastaPastaPasta PastaPastaPasta added this to the 20 milestone Sep 29, 2023
@knst
Copy link
Collaborator

knst commented Sep 30, 2023

otherwise gsl::not_null will call terminate.

I think assert is better than std::terminate, because with assert you can see backtrace when app is running in debugger.

@PastaPastaPasta
Copy link
Member Author

otherwise gsl::not_null will call terminate.

I think assert is better than std::terminate, because with assert you can see backtrace when app is running in debugger.

Well, we could change this to just be assert(false) then instead of calling std::terminate

@knst
Copy link
Collaborator

knst commented Oct 2, 2023

Well, we could change this to just be assert(false) then instead of calling std::terminate

Will we have in this case any error message in console (without debugger) such as "pointer X at file.cpp:NNN is null" also same as with assert? If so it's fine then

@PastaPastaPasta
Copy link
Member Author

Please take a look at this further set of changes and LMK what you think? it uses an early implementation of c++20's std::source_location that I think should be low cost; provides output now like
ERROR: error detected null not_null detected at dsnotificationinterface.cpp:41:57:AcceptedBlockHeader

Copy link
Collaborator

@knst knst left a comment

Choose a reason for hiding this comment

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

Concept ACK if it works as described

Btw, looks like magic for location of call

src/gsl/assert.h Outdated
{
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
(*gsl::details::get_terminate_handler())();
#else
std::cout << "ERROR: error detected null not_null detected at " << loc.file_name() << ":" << loc.line() << ":"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Std::cerr I think should be, also std::endl to flush buffer

@knst
Copy link
Collaborator

knst commented Oct 2, 2023

I think assert is better than std::terminate, because with assert you can see backtrace when app is running in debugger.

As I checked, at least gdb catches std::terminate without issues:

$ gdb -q main
Reading symbols from main...
(gdb) r
Starting program: /tmp/main 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
terminate called without an active exception

Program received signal SIGABRT, Aborted.
__pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:44
44      ./nptl/pthread_kill.c: No such file or directory.
(gdb) bt
#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=<optimized out>, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
#3  0x00007ffff783c406 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff782287c in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff7ca4ee6 in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007ffff7cb6e9c in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
#7  0x00007ffff7cb6f07 in std::terminate() () from /lib/x86_64-linux-gnu/libstdc++.so.6
#8  0x0000555555555156 in main () at main.cpp:4
(gdb) quit
A debugging session is active.

main.cpp:

#include <exception>

int main() {
    std::terminate();
}

So, std::terminate(), abort() and assert() behave are very similar in gdb and std::terminate seems completely fine.

Probably I got confused by exit() that is used in libjpeg/jpegturbo: https://github.com/winlibs/libjpeg/blob/master/jerror.c#L69
exit() is not caught by gdb even if code is not 0 indeed.

@github-actions
Copy link

github-actions bot commented Oct 3, 2023

This pull request has conflicts, please rebase.

src/Makefile.am Outdated Show resolved Hide resolved
src/llmq/quorums.cpp Outdated Show resolved Hide resolved
src/source_location.h Show resolved Hide resolved
src/source_location.h Outdated Show resolved Hide resolved
src/llmq/instantsend.cpp Outdated Show resolved Hide resolved
@UdjinM6
Copy link

UdjinM6 commented Oct 20, 2023

let's maybe have both cout and LogPrintf? UdjinM6@4eb326c

@knst
Copy link
Collaborator

knst commented Oct 21, 2023

It should not be stdout, but stderr

UdjinM6
UdjinM6 previously approved these changes Oct 21, 2023
Copy link

@UdjinM6 UdjinM6 left a comment

Choose a reason for hiding this comment

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

ACK

src/gsl/assert.h Outdated
#else
std::ostringstream s;
s << "ERROR: error detected null not_null detected at " << loc.file_name() << ":" << loc.line() << ":"
<< loc.column() << ":" << loc.function_name() << "\n";
Copy link
Member Author

Choose a reason for hiding this comment

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

Would it be better to use std::endl instead to ensure that it actually flushes?

Copy link

Choose a reason for hiding this comment

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

Yeah, we could do 3d69147. I doubt it would make any difference but 🤷‍♂️

Copy link

@UdjinM6 UdjinM6 left a comment

Choose a reason for hiding this comment

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

re-ACK

@PastaPastaPasta
Copy link
Member Author

LGTM

@PastaPastaPasta PastaPastaPasta merged commit c51cec6 into dashpay:develop Oct 22, 2023
@PastaPastaPasta PastaPastaPasta deleted the introduce-not-null-ptr branch October 22, 2023 14:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants