Boost logo

Boost :

Subject: Re: [boost] [serialization] basic_text_iprimitive destructor throws
From: John Salmon (john_at_[hidden])
Date: 2008-11-09 16:54:05


Here's a two-line patch (not counting the comment). This patch
simply ignores any ios_base::failure excpetions from is.sync(). There are
certainly other possibilities, but I don't see any good reason to prefer, e.g.,
checking the result of std::uncaught_exception() first or to broaden the
class of caught exceptions.

John

P.S. I've changed the subject to adhere to conventions.

salmonj_at_drdblogin6.en.desres$ diff -u
boost/archive/impl/basic_text_iprimitive.ipp.orig
boost/archive/impl/basic_text_iprimitive.ipp
--- boost/archive/impl/basic_text_iprimitive.ipp.orig 2008-11-09
16:32:30.003405292 -0500
+++ boost/archive/impl/basic_text_iprimitive.ipp 2008-11-09
16:38:51.755281718 -0500
@@ -147,7 +147,17 @@
 template<class IStream>
 BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
 basic_text_iprimitive<IStream>::~basic_text_iprimitive(){
- is.sync();
+ try{
+ is.sync();
+ }catch(std::ios_base::failure& e){
+ // is.sync might throw ios_base::failure if an error
+ // occurs and 'is' has the badbit exception
+ // mask set. Should this exception be allowed to "leak out"
+ // of this destructor:
+ // a) never?
+ // b) only if std::uncaught_exception() is false?
+ // c) under some other set of circumstances?
+ }
 }

 } // namespace archive
salmonj_at_drdblogin6.en.desres$

On Tue, Nov 4, 2008 at 4:17 PM, John Salmon <john_at_[hidden]> wrote:
> I tried turning on exceptions on the input stream that I use for a
> text_iarchive, hoping to catch user-level errors such as an attempt to
> treat a non-archive file as an archive. It seems that when exceptions
> are enabled on the underlying stream, the basic_text_iprimitive
> destructor throws a second(?) basic_ios::failure exception, during
> stack unwinding, which lands me unhappily in the terminate handler.
>
> Can the basic_text_iprimitive destructor be protected against
> accidentally throwing?
>
> Here's an demonstration. This is on a Linux system with gcc/4.1.2.
>
> John Salmon
>
> salmonj_at_drdblogin6.en.desres$ cat ser.cpp
> #include <boost/archive/text_iarchive.hpp>
> #include <boost/serialization/serialization.hpp>
> #include <stdexcept>
>
> #include <fstream>
>
> struct Foo{
> int i, j;
> private:
> friend class boost::serialization::access;
> template <class Archive>
> void serialize(Archive & ar, const unsigned int version)
> {
> ar & i & j;
> }
> };
>
> int main(){
> Foo foo;
> std::ifstream ifs("/dev/null");
> ifs.exceptions(std::istream::failbit | std::istream::badbit);
>
> try{
> boost::archive::text_iarchive tia(ifs);
> tia >> foo;
> }catch(std::ios_base::failure &e){
> std::cerr << "Caught std::ios_base::failure. What: " <<
> e.what() << "\n";
> }catch(std::exception &e){
> std::cerr << "Caught exception. What: " << e.what() << "\n";
> }
>
> return 0;
> }
>
> salmonj_at_drdblogin6.en.desres$ xmk
> g++ -I/proj/desres/root/Linux/x86_64/boost/1_37_0-13/Release/include
> -g -L/proj/desres/root/Linux/x86_64/boost/1_37_0-13/Release/lib
> -Wl,-rpath,/proj/desres/root/Linux/x86_64/boost/1_37_0-13/Release/lib
> ser.cpp -lboost_serialization -o ser
> salmonj_at_drdblogin6.en.desres$ ser
> terminate called after throwing an instance of 'std::ios_base::failure'
> what(): basic_ios::clear
> Aborted (core dumped)
> salmonj_at_drdblogin6.en.desres$ gdb -c
> drdblogin6.en.desres.deshaw.com-6718.core ser
> GNU gdb 6.8
> Copyright (C) 2008 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law. Type "show copying"
> and "show warranty" for details.
> This GDB was configured as "x86_64-unknown-linux-gnu"...
> Reading symbols from
> /proj/desrad-c/root/Linux/x86_64/boost/1_37_0-13/Release/lib/libboost_serialization.so...done.
> Loaded symbols for
> /proj/desres/root/Linux/x86_64/boost/1_37_0-13/Release/lib/libboost_serialization.so
> Reading symbols from
> /proj/desrad-c/root/Linux/x86_64/gcc/4.1.2-10/lib64/libstdc++.so.6...done.
> Loaded symbols for
> /proj/desres/root/Linux/x86_64/gcc/4.1.2-10/lib64/libstdc++.so.6
> Reading symbols from /lib64/tls/libm.so.6...done.
> Loaded symbols for /lib64/tls/libm.so.6
> Reading symbols from
> /proj/desrad-c/root/Linux/x86_64/gcc/4.1.2-10/lib64/libgcc_s.so.1...done.
> Loaded symbols for
> /proj/desres/root/Linux/x86_64/gcc/4.1.2-10/lib64/libgcc_s.so.1
> Reading symbols from /lib64/tls/libc.so.6...done.
> Loaded symbols for /lib64/tls/libc.so.6
> Reading symbols from /lib64/ld-linux-x86-64.so.2...done.
> Loaded symbols for /lib64/ld-linux-x86-64.so.2
> Core was generated by `ser'.
> Program terminated with signal 6, Aborted.
> [New process 6718]
> #0 0x0000003f72a2e25d in raise () from /lib64/tls/libc.so.6
> (gdb) where
> #0 0x0000003f72a2e25d in raise () from /lib64/tls/libc.so.6
> #1 0x0000003f72a2fa5e in abort () from /lib64/tls/libc.so.6
> #2 0x00002b5ab82f5f84 in __gnu_cxx::__verbose_terminate_handler ()
> at /state/partition1/tmp/tmpXcQw4O/gcc-4.1.2-10/gcc-4.1.2/libstdc++-v3/libsupc++/vterminate.cc:97
> #3 0x00002b5ab82f4106 in __cxxabiv1::__terminate (handler=0x1a3e)
> at /state/partition1/tmp/tmpXcQw4O/gcc-4.1.2-10/gcc-4.1.2/libstdc++-v3/libsupc++/eh_terminate.cc:43
> #4 0x00002b5ab82f350b in __cxa_call_terminate (ue_header=0x50b730)
> at /state/partition1/tmp/tmpXcQw4O/gcc-4.1.2-10/gcc-4.1.2/libstdc++-v3/libsupc++/eh_call.cc:60
> #5 0x00002b5ab82f3fa7 in __gxx_personality_v0 (
> version=<value optimized out>, actions=6,
> exception_class=<value optimized out>, ue_header=0x50b730,
> context=0x7ffff29e5610)
> at /state/partition1/tmp/tmpXcQw4O/gcc-4.1.2-10/gcc-4.1.2/libstdc++-v3/libsupc++/eh_personality.cc:637
> #6 0x00002b5ab846a068 in _Unwind_RaiseException_Phase2 (exc=0x50b730,
> context=0x7ffff29e5610)
> at /state/partition1/tmp/tmpXcQw4O/gcc-4.1.2-10/gcc-4.1.2/gcc/unwind.inc:66
> #7 0x00002b5ab846a2db in _Unwind_Resume (exc=0x50b730)
> at /state/partition1/tmp/tmpXcQw4O/gcc-4.1.2-10/gcc-4.1.2/gcc/unwind.inc:234
> #8 0x00002b5ab80fd790 in
> boost::archive::basic_text_iprimitive<std::istream>::~basic_text_iprimitive
> ()
> from /proj/desres/root/Linux/x86_64/boost/1_37_0-13/Release/lib/libboost_serialization.so
> #9 0x00002b5ab8109e0c in
> boost::archive::text_iarchive_impl<boost::archive::text_iarchive>::text_iarchive_impl
> ()
> from /proj/desres/root/Linux/x86_64/boost/1_37_0-13/Release/lib/libboost_serialization.so
> #10 0x00000000004045ab in text_iarchive (this=0x7ffff29e5ae0,
> is=@0x7ffff29e58d0, flags=0)
> at /proj/desres/root/Linux/x86_64/boost/1_37_0-13/Release/include/boost/archive/text_iarchive.hpp:110
> #11 0x0000000000402c84 in main () at ser.cpp:24
> (gdb) quit
> salmonj_at_drdblogin6.en.desres$
>


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