PR libstdc++/81256 fix exception handling in basic_filebuf::close
PR libstdc++/81256 * include/bits/fstream.tcc (basic_filebuf::close): Do not swallow exceptions from _M_terminate_output(). * include/std/fstream (basic_filebuf::~basic_filebuf): Swallow any exceptions from close(). * testsuite/27_io/basic_filebuf/close/81256.cc: New. From-SVN: r260236
This commit is contained in:
parent
10c54e5b0e
commit
e77497ab77
@ -1,5 +1,12 @@
|
||||
2018-05-14 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/81256
|
||||
* include/bits/fstream.tcc (basic_filebuf::close): Do not swallow
|
||||
exceptions from _M_terminate_output().
|
||||
* include/std/fstream (basic_filebuf::~basic_filebuf): Swallow any
|
||||
exceptions from close().
|
||||
* testsuite/27_io/basic_filebuf/close/81256.cc: New.
|
||||
|
||||
* include/bits/valarray_array.h (__valarray_get_memory): Remove.
|
||||
(__valarray_get_storage): Call operator new directly. Remove ignored
|
||||
top-level restrict qualifier and add malloc attribute instead.
|
||||
|
@ -239,13 +239,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
if (!_M_terminate_output())
|
||||
__testfail = true;
|
||||
}
|
||||
__catch(__cxxabiv1::__forced_unwind&)
|
||||
__catch(...)
|
||||
{
|
||||
_M_file.close();
|
||||
__throw_exception_again;
|
||||
}
|
||||
__catch(...)
|
||||
{ __testfail = true; }
|
||||
}
|
||||
|
||||
if (!_M_file.close())
|
||||
|
@ -244,7 +244,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
*/
|
||||
virtual
|
||||
~basic_filebuf()
|
||||
{
|
||||
__try
|
||||
{ this->close(); }
|
||||
__catch(...)
|
||||
{ }
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
basic_filebuf& operator=(const basic_filebuf&) = delete;
|
||||
|
109
libstdc++-v3/testsuite/27_io/basic_filebuf/close/81256.cc
Normal file
109
libstdc++-v3/testsuite/27_io/basic_filebuf/close/81256.cc
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-do run { target c++11 } }
|
||||
|
||||
#include <fstream>
|
||||
#include <locale>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
struct E : std::runtime_error
|
||||
{
|
||||
E() : runtime_error("") { }
|
||||
};
|
||||
|
||||
struct Cvt : std::codecvt<wchar_t, char, std::mbstate_t>
|
||||
{
|
||||
explicit Cvt(size_t refs) : codecvt(refs) { }
|
||||
|
||||
mutable int exceptions_thrown = 0;
|
||||
|
||||
private:
|
||||
int
|
||||
do_encoding() const noexcept override
|
||||
{ return -1; }
|
||||
|
||||
bool
|
||||
do_always_noconv() const noexcept override
|
||||
{ return false; }
|
||||
|
||||
result
|
||||
do_unshift(state_type&, char*, char*, char*&) const override
|
||||
{
|
||||
++exceptions_thrown;
|
||||
throw E();
|
||||
}
|
||||
};
|
||||
|
||||
struct filebuf : std::basic_filebuf<wchar_t>
|
||||
{
|
||||
explicit filebuf(Cvt* c)
|
||||
{
|
||||
std::locale loc(std::locale::classic(), c);
|
||||
imbue(loc);
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
// This facet needs to still be valid when ~basic_filebuf runs:
|
||||
Cvt conv{1};
|
||||
{
|
||||
filebuf fb(&conv);
|
||||
fb.open("output.txt", std::wios::out);
|
||||
fb.sputn(L"x", 1);
|
||||
|
||||
bool caught = false;
|
||||
try
|
||||
{
|
||||
/* [filebuf.members] p7: If one of these calls throws an exception,
|
||||
* the exception is caught and rethrown after closing the file. */
|
||||
fb.close();
|
||||
}
|
||||
catch (const E&)
|
||||
{
|
||||
caught = true;
|
||||
}
|
||||
VERIFY( conv.exceptions_thrown == 1 );
|
||||
VERIFY( caught );
|
||||
}
|
||||
VERIFY( conv.exceptions_thrown == 1 );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
// This facet needs to still be valid when ~basic_filebuf runs:
|
||||
Cvt conv{1};
|
||||
{
|
||||
filebuf fb(&conv);
|
||||
fb.open("output.txt", std::wios::out);
|
||||
fb.sputn(L"x", 1);
|
||||
/* [filebuf.cons] p5: If an exception occurs during the destruction
|
||||
* of the object, including the call to close(), the exception is
|
||||
* caught but not rethrown. */
|
||||
}
|
||||
VERIFY( conv.exceptions_thrown == 1 );
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
}
|
Loading…
Reference in New Issue
Block a user