Boost logo

Boost :

Subject: Re: [boost] [Stacktrace] review
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2016-12-16 15:24:46


On 12/16/16 22:32, Emil Dotchevski wrote:
> On Fri, Dec 16, 2016 at 1:20 AM, Andrey Semashev <andrey.semashev_at_[hidden]>
> wrote:
>
>> the argument wouldn't be whether or not capturing the
>>> stack trace is integrated into boost::throw_exception, but whether or not
>>> it is enabled by default. Either way, the boost::exception class (defined
>>> in boost/exception/exception.hpp) should provide a hook for that
>>> integration in order to avoid coupling between boost::throw_exception and
>>> Stacktrace.
>>
>> The way I see it, boost::exception already provides everything needed,
>> which is the ability to attach arbitrary data to the exception. I don't
>> think adding more special case capability to it is a wise solution in the
>> long term.
>
> This can be said about __FILE__ and __LINE__ which BOOST_THROW_EXCEPTION
> captures automatically. The reason why it's done is that 1) the cost in
> terms of time and space is considered negligible and 2) it is potentially
> critical for debugging.
>
> The reason why it Stacktrace would need special handling rather than go
> through the usual Boost Exception machinery is also the same as why there
> is special handling (members in boost::exception): to avoid coupling with
> the rest of the Boost Exception machinery, which is considerably heavier
> and bigger than boost/exception/exception.hpp.

The backtrace itself is not a lightweght object, so the overhead of the
generic Boost.Exception machinery is probably not significant. And if
that overhead is significant then maybe it could be optimized instead.
After all, why have it if we don't want to use it.

Also, note that the source location is always injected into the
exception (well, as long as you use BOOST_THROW_EXCEPTION or a similar
macro), while the backtrace is optional.

>> The run-time hook can be tricky to implement, that is true, but in the
>>>> simplest form it should be doable. The implementation details are of course
>>>> discussable, but below is something more concrete to get things started.
>>>>
>>>> Introduce a process-wide singleton pointer, which is a pointer to the
>>>> function that will augment the exception about to be thrown:
>>>>
>>>> typedef void (*exception_augmenter)(boost::exception&);
>>>>
>>>
> Consider dynamically loaded libraries.

That is a separate can of worms, which can ruin your day even without
the global pointer. The global hook doesn't make it worse per se.

> Also consider multiple libraries wanting different hooks.

That would be problematic to support - both with run-time and
compile-time hooks (the latter is difficult because of ODR violations).
I'm not sure this level of flexibility would be useful either.

> A process-wide pointer is very difficult to do in
> the general case, and I suspect it'd drag a lot more dependencies than
> capturing the stacktrace would.

The most complicated part is Windows-specific implementation, and it
only requires a few functions from WinAPI. Marking the pointer visible
on POSIX is trivial.

> Consider that boost::throw_exception must
> support very very old compilers.

How old? I mean, it only has to support the oldest compiler Boost
libraries support.

> Besides, throwing exceptions and capturing stack trace are thread-local
> operations, while global pointer would require synchronization with the
> initialization code.

That's a valid concern, but I think it can be mitigated by caching the
pointer.

We could also accept the limitation that the augmentor has to be
installed once at the beginning of the program and simply not support
its multithreaded modification.

> Are you proposing to include <windows.h> in boost/throw_exception.hpp?
> That's a no-go.

No. Use approach similar to Boost.WinAPI on Windows (i.e. re-declare
WinAPI components).

> Making it not header-only module? Also a no-go.

No.


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