-
-
Notifications
You must be signed in to change notification settings - Fork 541
Backtrace screen (improvements over #1270) #1821
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
base: main
Are you sure you want to change the base?
Conversation
|
Can you note, which commits for the first vs. second part? I assume the first commit ("Rename *" for the first and the remaining 4 later? I think we can also do this all at once. But I'm ope on that front. |
Yes, the first commit is the option rename, and the remaining 4 commits are the new feature / configure options. The reason I suggest the rename is that |
|
Do we have alternative backends for backtracing/demangling besides unwind-ptrace and iberty? Given there's both an unwind implementation in LLVM and GCC, what else are sensible alternatives that warrent implementation of the |
Well, I don't know what other libraries are possible for the backtrace feature, but I leave room for those new backends. For the demangling function, I can see libdemangle from Solaris / Sun Studio as a possible alternative, but I didn't check that yet. It's better for @MrCirdo 's code (#1270) get merged first before considering alternatives. |
|
NP. No need to decide on all the possible backends and variants now. That's something we can leave open for the first implementation. Priority is getting things work; make them flexible and fast is the next step. No need to over-engineer things from the get-go. I just wanted to evaluate if there's a reasonable need for allowing the backends for backtraces and demangling to be replaced. |
a964363 to
798b603
Compare
798b603 to
9ced4f4
Compare
| } | ||
|
|
||
| if (pid <= 0) { | ||
| xAsprintf(error, "Unable to get the pid"); |
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 pid <= 0 check can be moved to before the unw_create_addr_space call. That way we can save an allocation and deallocation in case when the PID is invalid.
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.
Yes, you're alright! Good Catch!
| unw_word_t pc; | ||
|
|
||
| BacktraceFrameData* frame = BacktraceFrameData_new(); | ||
| frame->index = index; |
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.
Do we really need this index field in the BacktraceFrameData structure? Since the vector object of BacktraceFrameData is likely sorted by index already, we can derive the indices when showing the backtrace data.
A technical advantage of leaving out this field is that a BacktraceFrameData can then initialize to all zeros. That saves code size.
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.
Your argument makes sense. Sometimes, when unw_get_proc_name returns an error, what I was doing was to skip the frame. However, to keep the display coherent, this index was introduced. It can be removed.
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.
@MrCirdo In case there is a failure in processing an entry in the list (such as a process name among a list of processes), a dummy entry can be added to indicate the error to keep the index numbering sane (when displayed).
| if (unw_get_elf_filename(&cursor, elfFileName, sizeof(elfFileName), &offsetElfFileName) == 0) { | ||
| frame->objectPath = xStrndup(elfFileName, 2048); | ||
|
|
||
| char *lastSlash = strrchr(frame->objectPath, '/'); |
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.
strrchr() can return NULL when the input string frame->objectPath contains no slashes.
This can cause the xStrndup(lastSlash + 1, 2048); to dereference an invalid pointer. We definitely need a null pointer check here.
(Thanks to the basename() API hell in libiberty that I discovered this one - an unsafe imitate of basename().)
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.
Well See! I didn't catch this one! I'll fix it!
Great! Perfect! Thank you very much!
With pleasure! Wait, let’s get on the same page @Explorer09. My primary concern about supporting the BSD platform (FreeBSD, NetBSD, macOS, etc) is that I don't know if NB : Sorry if I take time to answer because I need to do some preparation for a coding interview. |
I didn't test running the code on BSD yet. The only thing I've tested is building htop with libunwind-ptrace and libiberty on FreeBSD on a CI server. I've read the man page of My aim is to make it buildable in Linux and FreeBSD; other OSes are too difficult and I would expect libunwind port to those platforms first before we try making our backtrace feature work there. |
I.e. no further changes from @Explorer09 unless needed/requested. And possibly rebases onto main maybe.
I think this PR will likely stay as is; i.e. no major changes.
You can ask @fraggerfox regarding NetBSD details if necessary.
NP. |
The libunwind README says its supported operating systems are Linux, FreeBSD, Solaris, QNX and HP-UX (partially). NetBSD is not included. For Solaris, there's no pre-built binary package for libunwind so testing on it would be difficult. QNX and HP-UX are out of htop's scope. So there remains Linux and FreeBSD, which are what I tried to make htop's backtrace work for. |
f394979 to
dd9cf40
Compare
The configure option '--enable-unwind' doesn't actually enable a feature in htop but selects a library dependency for a feature (printing local backtrace for this case). Use a '--with-' naming to reflect the option's purpose better. For backward compatibility (with automated build scripts), using '--enable-unwind' will still work but it will print a warning. Signed-off-by: Kang-Che Sung <[email protected]>
Co-authored-by: Odric Roux-Paris <[email protected]> Co-authored-by: Benny Baumann <[email protected]> Signed-off-by: Kang-Che Sung <[email protected]>
Co-authored-by: Odric Roux-Paris <[email protected]> Co-authored-by: Benny Baumann <[email protected]> Signed-off-by: Kang-Che Sung <[email protected]>
Co-authored-by: Odric Roux-Paris <[email protected]> Co-authored-by: Benny Baumann <[email protected]> Signed-off-by: Kang-Che Sung <[email protected]>
For Linux and FreeBSD build jobs.
Signed-off-by: Kang-Che Sung <[email protected]>
Co-authored-by: Benny Baumann <[email protected]>
dd9cf40 to
86faa3d
Compare
|
|
||
| char* buf; | ||
|
|
||
| while (!!(buf = malloc(allocSize))) { |
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 would use realloc(3) here if the size is too small. What do you think?
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.
Using realloc is not helpful here because the buffer may be free'd for other reasons. realloc is best used on buffers with content you need to preserve, which is not the case here.
Perfect! 😄 I closed the first one. Can I push on your branch @Explorer09 to fix the problem you emphasized? |
I have enabled push access for this particular branch |
| #ifdef HAVE_DEMANGLING | ||
| char* Generic_Demangle(const char* mangled) { | ||
| # if defined(HAVE_LIBIBERTY_CPLUS_DEMANGLE) | ||
| int options = DMGL_PARAMS | DMGL_AUTO; |
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.
As mentioned in #1270, I would like to document the reasoning on the choice regarding the 6 boolean flags supported by cplus_demangle function:
DMGL_PARAMS, DMGL_ANSI, DMGL_VERBOSE, DMGL_TYPES, DMGL_RET_POSTFIX and DMGL_RET_DROP
For now I recognised why the use of DMGL_PARAMS here (necessary for C++ to distinguish function overloads), but haven't looked up on what the other 5 options do.
This branch is experimental and related to #1270 (the backtrace screen feature).
I've written and improved the configure script so that it can check
libunwind-ptraceandlibibertyfor the backtrace feature proposed in #1270.The changes come with two parts:
The first part can be reviewed and cherry-picked into
mainearly. It renames the configure option--enable-unwindto--with-libunwindto better reflect it's purpose. The old option name is preserved for compatibility but will trigger warnings when used.The second part consists of several commits that add the new configure options
--enable-backtraceand--enable-demanglingand the checking code oflibunwind-ptraceandlibiberty. The code might look large and complicated, but I've tried a lot on the usability and correctness of the check. For example thislibunwind-ptracecheck can work with and withoutpkg-config, and I tried to ensure thecplus_demangle()function has a correct prototype.The
libunwind-ptraceandlibibertylibraries can be detected both in Linux and in FreeBSD. However, I haven't ported the backtrace screen code from @MrCirdo to ensure they really build, especially in FreeBSD.