Boost logo

Boost :

Subject: Re: [boost] Stacktrace library starts review today 14th Dec
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2016-12-17 16:01:15


On Sat, Dec 17, 2016 at 9:32 PM, Antony Polukhin <antoshkka_at_[hidden]> wrote:
>
> I'd like to discuss a proposed changes. Thing that I'm worried about:
> * replacing class `stacktrace` with vector<void*> will definitely
> break the most common use case std::cout << get_stacktrace(); as it's
> not a good idea to overload ostream operator for vector of void
> pointers

No, I wasn't suggesting to replace `stacktrace` with `vector<void*>`.
I was suggesting it as a possible implementation of `stacktrace` (i.e.
an internal data member of the `stacktrace` class). And BTW, that
should probably be `vector<frame>` to support proper container
semantics in `stacktrace`.

I've given it some more thought after I wrote the review, and it
occurred to me that the main reason for the current implementation of
`basic_stacktrace` as an array is probably the intention to allow its
use in signal handlers. For some reason it didn't occur to me while I
was writing the review. That is a fair goal, although I'm having a
hard time thinking of what can be done with a stacktrace from a signal
handler. I guess, the only thing that can be done is dumping it into a
file, but the library does not provide such a facility (the
`operator<<` is not suitable for this).

Of course, `vector` is not an option in a signal handler, but the
runtime-sized `basic_stacktrace` can still be used in this case. The
idea is to offer a way to provide an external storage for the
`basic_stacktrace` object, which would be an array of `frame`s in this
case. It could look something like this:

  void my_signal_handler(int sig)
  {
    boost::stacktrace::frame frames[10];
    boost::stacktrace::stacktrace bt{ frames, 10 }; // bt.size() == 0
&& bt.capacity() == 10
    boost::stacktrace::fill_stacktrace(bt); // makes bt.size() <= 10
  }

Internally, `stacktrace` should be smart enough to handle three cases
wrt. the buffer of frames:

1. The `stacktrace` object refers to an external buffer. It should not
deallocate the frames.
2. The `stacktrace` object owns a small amount of frames stored in the
internal array (e.g. up to 8 frames). The frames should be destroyed
with the `stacktrace` object.
3. The `stacktrace` object owns a large amount of frames, allocated
dynamically on heap. The frames should be destroyed and deallocated
with the `stacktrace` object.

Copying and assignment should also work with these three states.

> * addr2line and forking is not nice. Is linking with a GPL licensed
> code an acceptable alternative?

I think it would be difficult to get it accepted, but probably
possible if it's a separate header, on which nothing from the rest of
the library depends. Of course, the most preferable solution is to
have the whole library licensed under BSL.

Maybe there is a different implementation of the functionality
provided by addr2line? Niall mentioned a tool from LLVM, maybe its
code can be reused (and I'm assuming it's licensed under BSD).

> * removing `basic_stacktrace` will definitely remove all the
> possibilities for optimization of caching COM/parsed DWARF. This is a
> quick win that later may turn into big troubles.

Again, I wasn't suggesting to remove `stacktrace` - on the contrary,
the stacktrace should be represented with a distinct type. What I'm
having the problem with is what semantics you put into that type.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk