Code Monkey home page Code Monkey logo

Comments (30)

dmenendez-gruposantander avatar dmenendez-gruposantander commented on August 29, 2024 1

Any chance to get this into the 1.73 release?
Is there anything else I can help with?

from exception.

zajo avatar zajo commented on August 29, 2024

It is unclear to me who the target audience for such rerouting would be.

If you use boost::throw_exception() to throw, then boost::current_exception() / boost::rethrow_exception() work as well as std::current_exception() / std::rethrow_exception(), but you must use the boost versions if you do need your code to work on old compilers; if you don't, you may (should?) use the std versions.

If you don't use boost::throw_exception() to throw, then you should always use the std::current_exception() / std::rethrow_exception(), since your code won't work correctly on old compilers anyway.

Secondly, there are other components in Boost, e.g. boost::function, which aren't "rerouted". If such rerouting is needed, it should probably be done uniformly for all such components, though I'm not sure if there are important subtle semantic differences (there probably are.)

from exception.

ned14 avatar ned14 commented on August 29, 2024

This rerouting would only apply on C++ 11 or newer, and presumably only on compilers without borked std::current_exception().

I get the argument "why bother rerouting?". But there is also the argument "why not bother rerouting?". Unlike boost::function, as far as I am aware, there is zero known behavioural differences between std::current_exception/rethrow_exception and boost::current_exception/rethrow_exception. Plus, rerouting these keeps symmetry with the rerouting of Boost.System to its std equivalents.

from exception.

zajo avatar zajo commented on August 29, 2024

My question wasn't so much "why", but who would benefit? I understand the motivation, and I'm not against it in principle, but I am worried about possibly breaking client code which currently works fine, and I think that it is important to understand who cares about this change.

The safe approach would be to provide a new configuration macro, e.g. BOOST_EXCEPTION_USE_STD_EXCEPTION_PTR (off by default), which would guarantee nothing will break. Would that work? This isn't just paranoia, recently I tried to remove the support for non-intrusive boost::exception_ptr, specific for MSVC, thinking that probably nobody uses it any more (since modern compilers have std::exception_ptr), but it turned out I was wrong, so that's back in.

(By the way, I am not aware of any differences between std::function and boost::function, when I changed the allocator support in boost::function to match that of boost::shared_ptr, I wrote a proposal which made it into the standard as well :). But possibly I'm missing something.)

from exception.

zajo avatar zajo commented on August 29, 2024

Actually I've realized that there is another problem: the custom error info container in boost::exception is held by a boost::shared_ptr, and all copies of a boost::exception object share that state. Only when making a boost::exception_ptr, the copied exception object doesn't share that state with the source, but that copy is not created using the copy constructor. A copy created by std::current_exception would share that state, potentially with explosive consequences if the exception is transported to another thread.

While this design is not ideal and can probably be safely changed so boost::exception objects never share state, this would not be a trivial change.

from exception.

jeking3 avatar jeking3 commented on August 29, 2024

This discussion stalled, was there a conclusion (for example, since it was not trivial, will we do it?)

from exception.

zajo avatar zajo commented on August 29, 2024

I don't know if this can be fixed. I'll try to explain simpler:

A boost::exception object holds a map of data, through a custom intrusive refcounting smart pointer. Copying exception objects within a thread only changes the refcount.

But that map is not thread-safe, so when a boost::exception object is transported to another thread, we must create a copy of the map, which boost::current_exception knows and does, but std::current_exception would simply invoke the copy constructor, which won't copy the map.

Maybe it can be done with a move constructor, but this would require #ifdefing, since I don't think it's a good idea to break C++03 support.

I'll close this for now, if anyone has an idea for a workaround, feel free to reopen and continue the discussion.

from exception.

dariomt avatar dariomt commented on August 29, 2024

I have a suggestion (that would solve my use case):

  1. first have boost::current_exception() do its current work, and recover the exception_ptr
  2. then, if this 'failed' (and we would get an exception_ptr pointing to an unknown_exception), reroute to std::current_exception() if supported

This would:
a) keep existing code using Boost.Exception facilities working correctly
b) make code not using Boost.Exception to throw, work correctly, as if std::current_exception was used

For reference, in my use case I need to

  • use boost::future (which uses boost::current_exception() to transport exceptions across threads)
  • but I cannot use Boost.Exception facilities to throw exceptions (third party code throwing)

Does this make sense?

from exception.

zajo avatar zajo commented on August 29, 2024

Reroute to std::current_exception, how? std::exception_ptr and boost::exception_ptr are different types.

from exception.

dariomt avatar dariomt commented on August 29, 2024

Hum... maybe wrap the std::exception_ptr in current_exception and unwrap it in rethrow_exception?

In boost::exception_detail::current_exception_impl() (around boost/exception/detail/exception_ptr.hpp:424 in boost 1.64)

catch(...)
{
   try {
        // wrap the std::exception_ptr in a clone-enabled Boost.Exception object
       return exception_ptr(shared_ptr<exception_detail::clone_base const>(
              boost::enable_current_exception(std::current_exception()).clone()));
    }
   catch(...) {
      return exception_detail::current_exception_unknown_exception();
   }
}

In boost::rethrow_exception():

   try {
        p.ptr_->rethrow();
    } catch (const std::exception_ptr& ep) {
            std::rethrow_exception(ep);
   }

This (pseudo)code is for exposition only. Also, for simplicity this code assumes std::current_exception is available. I could provide a PR if necessary, but I doubt I can get all the #ifdef-ing right!

PS: I took inspiration from https://stackoverflow.com/questions/22010388/converting-stdexception-ptr-to-boostexception-ptr/22881981

from exception.

dariomt avatar dariomt commented on August 29, 2024

I'm testing the above locally and it looks like it works. Two caveats, though:

  1. clone is private so we need a reference to the base class
exception_detail::clone_base const& base {
    boost::enable_current_exception(std::current_exception())};
return exception_ptr(shared_ptr<exception_detail::clone_base const>(base.clone()));
  1. the catch(std::exception&) (that redirects to current_exception_unknown_std_exception()) above the catch all clause, is intercepting my user defined exception type (which inherits from std::exception) so I had to remove it for this to work. Not sure if that breaks anything, as the std::current_exception should transport that case correctly.

What do you think?

from exception.

zajo avatar zajo commented on August 29, 2024

Oh I see, your idea is to use std::exception_ptr as a way to be able to clone any exception properly, but still returning a boost::exception_ptr. I had misunderstood, I thought you wanted to go the other way around, to be able to effectively make boost::exception_ptr be std::exception_ptr where available.

This is a great idea, thank you. Since you said you've tested, I'm assuming you can send a pull request?

from exception.

dariomt avatar dariomt commented on August 29, 2024

I'm testing locally against Boost 1.64.0. I guess you'd like the PR against devel branch?

Also, do you know which Boost preprocessor macro can I use to detect support for std::exception_ptr?

from exception.

zajo avatar zajo commented on August 29, 2024

There is no config macro in Boost to detect std::exception_ptr support. Probably just check for C++11 support (e.g. #if __cplusplus > 199711L) and assume std::exception_ptr is available.

You can send a diff with Boost 1.64.0 if that's easier. I'll review and commit manually. Thank you!

from exception.

dariomt avatar dariomt commented on August 29, 2024

My main compiler is VS2015, so I'm afraid __cplusplus does not work for me: for some reason it's still defined to be 199711L.
I'm looking at Boost.Config and I can't find anything suitable.
Maybe I can just use BOOST_NO_CXX11_NOEXCEPT, and assume that if noexcept is supported, then std::current_exception is also supported?
Or maybe I should bring this up in the mailing list?

from exception.

zajo avatar zajo commented on August 29, 2024

It can't hurt to talk on the mailing list. But it may be safe to assume exception_ptr is supported if __cplusplus is greater than 199711L.

from exception.

dmenendez-gruposantander avatar dmenendez-gruposantander commented on August 29, 2024

I'm working to provide a PR over develop branch.

BTW, my boss gave me green light to do this task using company time, so I'll do this with my corporatey github account, just to clarify I'm not doing this in my own free time.

from exception.

dmenendez-gruposantander avatar dmenendez-gruposantander commented on August 29, 2024

About the docs, should I update the html files under doc/ directly?
I thought there would be some other source from which the html files are generated...

from exception.

dmenendez-gruposantander avatar dmenendez-gruposantander commented on August 29, 2024

The changes (code, tests and docs) are ready in my fork (https://github.com/dmenendez-gruposantander/exception).
However I have a dependency on Boost.Config PR boostorg/config#285 being merged to develop (for BOOST_NO_CXX11_HDR_EXCEPTION).
Which is stalled due to CI testing being borked right now :(
I'll create a PR as soon as #285 is merged to develop.

from exception.

zajo avatar zajo commented on August 29, 2024

Yes, let's wait until the config change gets merged, and then I'll look at the PR. Thank you!

from exception.

dmenendez-gruposantander avatar dmenendez-gruposantander commented on August 29, 2024

Now that the Boost.Config changes have been merged to develop (thanks @jzmaddock!) I've created PR #24 with my changes, so let the code review begin!

Unfortunately, some CI tests are unexpectedly failing, and I'm having a hard time deciphering the errors...
For some versions of gcc it seems confused about instantiating abstract class clone_base (which I'd say I'm not) and the clang tests I don't think are even related to my changes!

Any help with this is appreciated, as I am being optimistic and was hoping to get this merged in time for the 1.72 release.

from exception.

pdimov avatar pdimov commented on August 29, 2024

The clang errors are because Travis switched to Xenial by default; dist: trusty needs to be added to .travis.yml as the old clang versions don't work on Xenial.

from exception.

dmenendez-gruposantander avatar dmenendez-gruposantander commented on August 29, 2024

Hum... This is not something I should fix in my PR, is it?

from exception.

dmenendez-gruposantander avatar dmenendez-gruposantander commented on August 29, 2024

Is there something I can do to help with this issue?
Not that I'm familiar with the CI setting, but if all it takes is "dist: trusty needs to be added to .travis.yml" then I could... create a PR for that?

from exception.

dmenendez-gruposantander avatar dmenendez-gruposantander commented on August 29, 2024

Hi, I'm sorry to be nagging about this, but I don't see how I can get this PR merged...
Is the CI config already fixed?
How do I "retry" the PR?
I'd really like to get this merged for 1.72, please.

from exception.

dmenendez-gruposantander avatar dmenendez-gruposantander commented on August 29, 2024

OK, I added dist: trusty in my PR and the clang problems are solved.

However I still have problem with old versions of gcc which get confused when I bind a exception_detail::clone_base const& to the temporary coming out of boost::enable_current_exception().
Somehow gcc thinks I want a copy!
Ideas?

I tried const auto& but the actual type returned from boost::enable_current_exception() has clone() as a private member function!

from exception.

dmenendez-gruposantander avatar dmenendez-gruposantander commented on August 29, 2024

At last! All tests are green!
Could you review the proposed changes for this PR please?

PS: the gcc problem was due to initializing the reference with braces instead of using =
go figure! slaps face

from exception.

zajo avatar zajo commented on August 29, 2024

Yes, I'll look at it. Thank you!

from exception.

dmenendez-gruposantander avatar dmenendez-gruposantander commented on August 29, 2024

In my last (and first) contribution to Boost I was asked about Copyright.
I'm never sure about how to proceed with this, if it should be part of the PR or where it should appear.

This is it, in case it's necessary:
Copyright 2019 Dario Menendez, Banco Santander

from exception.

zajo avatar zajo commented on August 29, 2024

Done.

from exception.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.