Skip to content

Commit 6d57f92

Browse files
author
Kjell Ahlstedt
committed
Work around some platforms' lack of support for std::exception_ptr
* libxml++/exceptions/exception.[cc|h]: * libxml++/exceptions/internal_error.[cc|h]: * libxml++/exceptions/parse_error.[cc|h]: * libxml++/exceptions/validity_error.[cc|h]: Reintroduce Raise() and Clone(), now renamed to raise() and clone(). * libxml++/exceptions/wrapped_exception.[cc|h]: Reintroduced files, now with the wrapped_exception class declared only if LIBXMLXX_HAVE_EXCEPTION_PTR is defined. * libxml++/filelist.am: Add wrapped_exception.h. * libxml++/parsers/parser.[cc|h]: Replace std::exception_ptr exception_ptr_ by std::unique_ptr<xmlpp::exception> exception_. * libxml++/parsers/saxparser.cc: exception_ptr_ -> exception_ * libxml++/parsers/saxparser.h: Note in the class description that some exceptions are replaced by xmlpp::exception if std::exception_ptr is not supported. * libxml++/validators/validator.[cc|h]: Replace std::exception_ptr exception_ptr_ by std::unique_ptr<xmlpp::exception> exception_. * examples/sax_exception/myparser.[cc|h]: Reintroduce Raise() and Clone(), now renamed to raise() and clone(). * tests/saxparser_chunk_parsing_inconsistent_state/main.cc: * tests/saxparser_parse_double_free/main.cc: * tests/saxparser_parse_stream_inconsistent_state/main.cc: Catch xmlpp::exception, if LIBXMLXX_HAVE_EXCEPTION_PTR is not defined. Bug #757042. The substitution of exception_ for exception_ptr_ in Parser and Validator breaks ABI. The ABI of libxml++ 3.x has not yet been frozen. Thanks to Daniel Trebbien <dtrebbien@gmail.com>, who supplied a patch for libxml++ 2.40.
1 parent 58dbe5c commit 6d57f92

File tree

22 files changed

+313
-78
lines changed

22 files changed

+313
-78
lines changed

examples/sax_exception/myparser.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ MyException::~MyException() throw ()
3434
{
3535
}
3636

37+
void MyException::raise() const
38+
{
39+
throw *this;
40+
}
41+
42+
xmlpp::exception* MyException::clone() const
43+
{
44+
return new MyException(*this);
45+
}
46+
3747
/*
3848
* MySaxParser implementation
3949
*/

examples/sax_exception/myparser.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class MyException: public xmlpp::exception
2727
public:
2828
MyException();
2929
~MyException() noexcept override;
30+
void raise() const override;
31+
xmlpp::exception* clone() const override;
3032
};
3133

3234
class MySaxParser : public xmlpp::SaxParser

libxml++/exceptions/exception.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ const char* exception::what() const noexcept
1919
return message_.c_str();
2020
}
2121

22+
void exception::raise() const
23+
{
24+
throw *this;
25+
}
26+
27+
exception* exception::clone() const
28+
{
29+
return new exception(*this);
30+
}
31+
2232
Glib::ustring format_xml_error(const _xmlError* error)
2333
{
2434
if (!error)

libxml++/exceptions/exception.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ class LIBXMLPP_API exception : public std::exception
4444

4545
const char* what() const noexcept override;
4646

47+
virtual void raise() const;
48+
virtual exception* clone() const;
49+
4750
private:
4851
Glib::ustring message_;
4952
};

libxml++/exceptions/internal_error.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,14 @@ internal_error::internal_error(const Glib::ustring& message)
1010
internal_error::~internal_error() noexcept
1111
{}
1212

13+
void internal_error::raise() const
14+
{
15+
throw *this;
16+
}
17+
18+
exception* internal_error::clone() const
19+
{
20+
return new internal_error(*this);
21+
}
22+
1323
} //namespace xmlpp

libxml++/exceptions/internal_error.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ class internal_error : public exception
2929
public:
3030
explicit internal_error(const Glib::ustring& message);
3131
~internal_error() noexcept override;
32+
33+
void raise() const override;
34+
exception* clone() const override;
3235
};
3336

3437
} // namespace xmlpp

libxml++/exceptions/parse_error.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,14 @@ parse_error::parse_error(const Glib::ustring& message)
1010
parse_error::~parse_error() noexcept
1111
{}
1212

13+
void parse_error::raise() const
14+
{
15+
throw *this;
16+
}
17+
18+
exception* parse_error::clone() const
19+
{
20+
return new parse_error(*this);
21+
}
22+
1323
} //namespace xmlpp

libxml++/exceptions/parse_error.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ class parse_error : public exception
3232
public:
3333
explicit parse_error(const Glib::ustring& message);
3434
~parse_error() noexcept override;
35+
36+
void raise() const override;
37+
exception* clone() const override;
3538
};
3639

3740
} // namespace xmlpp

libxml++/exceptions/validity_error.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,14 @@ validity_error::validity_error(const Glib::ustring& message)
1010
validity_error::~validity_error() noexcept
1111
{}
1212

13+
void validity_error::raise() const
14+
{
15+
throw *this;
16+
}
17+
18+
exception* validity_error::clone() const
19+
{
20+
return new validity_error(*this);
21+
}
22+
1323
} //namespace xmlpp

libxml++/exceptions/validity_error.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ class validity_error : public parse_error
3232
public:
3333
explicit validity_error(const Glib::ustring& message);
3434
~validity_error() noexcept override;
35+
36+
void raise() const override;
37+
exception* clone() const override;
3538
};
3639

3740
} // namespace xmlpp
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/* Copyright (C) 2015 The libxml++ development team
2+
*
3+
* This library is free software; you can redistribute it and/or
4+
* modify it under the terms of the GNU Lesser General Public
5+
* License as published by the Free Software Foundation; either
6+
* version 2.1 of the License, or (at your option) any later version.
7+
*
8+
* This library is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+
* Lesser General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU Lesser General Public
14+
* License along with this library; if not, write to the Free Software
15+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16+
*/
17+
18+
#include "wrapped_exception.h"
19+
20+
namespace xmlpp
21+
{
22+
23+
#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
24+
25+
wrapped_exception::wrapped_exception(std::exception_ptr exception_ptr)
26+
: exception("Wrapped exception"), exception_ptr_(exception_ptr)
27+
{
28+
}
29+
30+
wrapped_exception::~wrapped_exception() noexcept
31+
{
32+
}
33+
34+
void wrapped_exception::raise() const
35+
{
36+
std::rethrow_exception(exception_ptr_);
37+
}
38+
39+
exception* wrapped_exception::clone() const
40+
{
41+
return new wrapped_exception(exception_ptr_);
42+
}
43+
44+
#endif // LIBXMLXX_HAVE_EXCEPTION_PTR
45+
46+
} // namespace xmlpp
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/* Copyright (C) 2015 The libxml++ development team
2+
*
3+
* This library is free software; you can redistribute it and/or
4+
* modify it under the terms of the GNU Lesser General Public
5+
* License as published by the Free Software Foundation; either
6+
* version 2.1 of the License, or (at your option) any later version.
7+
*
8+
* This library is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+
* Lesser General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU Lesser General Public
14+
* License along with this library; if not, write to the Free Software
15+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16+
*/
17+
18+
#ifndef __LIBXMLPP_WRAPPED_EXCEPTION_H
19+
#define __LIBXMLPP_WRAPPED_EXCEPTION_H
20+
21+
#include <exception>
22+
23+
#include <libxml++/exceptions/exception.h>
24+
#include <libxml++config.h>
25+
26+
namespace xmlpp
27+
{
28+
29+
#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
30+
31+
#ifndef DOXYGEN_SHOULD_SKIP_THIS
32+
/** Helper class for propagating an exception through C code.
33+
* Should not be used by applications.
34+
* Does not exist in systems that don't support std::exception_ptr.
35+
*
36+
* @newin{2,40}
37+
*/
38+
class wrapped_exception : public exception
39+
{
40+
public:
41+
explicit wrapped_exception(std::exception_ptr exception_ptr);
42+
~wrapped_exception() noexcept override;
43+
44+
void raise() const override;
45+
exception* clone() const override;
46+
47+
private:
48+
std::exception_ptr exception_ptr_;
49+
};
50+
#endif //DOXYGEN_SHOULD_SKIP_THIS
51+
52+
#endif // LIBXMLXX_HAVE_EXCEPTION_PTR
53+
54+
} // namespace xmlpp
55+
56+
#endif // __LIBXMLPP_WRAPPED_EXCEPTION_H

libxml++/filelist.am

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ h_exceptions_sources_public = \
1515
exceptions/exception.h \
1616
exceptions/parse_error.h \
1717
exceptions/validity_error.h \
18-
exceptions/internal_error.h
18+
exceptions/internal_error.h \
19+
exceptions/wrapped_exception.h
1920
h_io_sources_public = \
2021
io/istreamparserinputbuffer.h \
2122
io/outputbuffer.h \

libxml++/parsers/parser.cc

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* included with libxml++ as the file COPYING.
55
*/
66

7+
#include "libxml++/exceptions/wrapped_exception.h"
78
#include "libxml++/parsers/parser.h"
89

910
#include <libxml/parser.h>
@@ -34,7 +35,7 @@ struct Parser::Impl
3435
};
3536

3637
Parser::Parser()
37-
: context_(nullptr), exception_ptr_(nullptr), pimpl_(new Impl)
38+
: context_(nullptr), exception_(nullptr), pimpl_(new Impl)
3839
{
3940
}
4041

@@ -193,20 +194,7 @@ void Parser::on_validity_warning(const Glib::ustring& message)
193194

194195
void Parser::check_for_error_and_warning_messages()
195196
{
196-
Glib::ustring msg;
197-
try
198-
{
199-
if (exception_ptr_)
200-
std::rethrow_exception(exception_ptr_);
201-
}
202-
catch (const std::exception& e)
203-
{
204-
msg = e.what();
205-
}
206-
catch (...)
207-
{
208-
msg = "Unknown exception\n";
209-
}
197+
Glib::ustring msg(exception_ ? exception_->what() : "");
210198
bool parser_msg = false;
211199
bool validity_msg = false;
212200

@@ -238,17 +226,10 @@ void Parser::check_for_error_and_warning_messages()
238226
pimpl_->validate_warning_.erase();
239227
}
240228

241-
try
242-
{
243-
if (validity_msg)
244-
throw validity_error(msg);
245-
else if (parser_msg)
246-
throw parse_error(msg);
247-
}
248-
catch (...)
249-
{
250-
exception_ptr_ = std::current_exception();
251-
}
229+
if (validity_msg)
230+
exception_.reset(new validity_error(msg));
231+
else if (parser_msg)
232+
exception_.reset(new parse_error(msg));
252233
}
253234

254235
//static
@@ -339,7 +320,30 @@ void Parser::callback_error_or_warning(MsgType msg_type, void* ctx,
339320

340321
void Parser::handle_exception()
341322
{
342-
exception_ptr_ = std::current_exception();
323+
try
324+
{
325+
throw; // Re-throw current exception
326+
}
327+
catch (const exception& e)
328+
{
329+
exception_.reset(e.clone());
330+
}
331+
#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
332+
catch (...)
333+
{
334+
exception_.reset(new wrapped_exception(std::current_exception()));
335+
}
336+
#else
337+
catch (const std::exception& e)
338+
{
339+
exception_.reset(new exception(e.what()));
340+
}
341+
catch (...)
342+
{
343+
exception_.reset(new exception("An exception was thrown that is not derived from std::exception or xmlpp::exception.\n"
344+
"It could not be caught and rethrown because this platform does not support std::exception_ptr."));
345+
}
346+
#endif
343347

344348
if (context_)
345349
xmlStopParser(context_);
@@ -351,11 +355,10 @@ void Parser::check_for_exception()
351355
{
352356
check_for_error_and_warning_messages();
353357

354-
if (exception_ptr_)
358+
if (exception_)
355359
{
356-
std::exception_ptr tmp(exception_ptr_);
357-
exception_ptr_ = nullptr;
358-
std::rethrow_exception(tmp);
360+
std::unique_ptr<exception> tmp(std::move(exception_));
361+
tmp->raise();
359362
}
360363
}
361364

libxml++/parsers/parser.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include <istream>
2020
#include <cstdarg> // va_list
2121
#include <memory> // std::unique_ptr
22-
#include <exception> // std::exception_ptr
2322

2423
#ifndef DOXYGEN_SHOULD_SKIP_THIS
2524
extern "C" {
@@ -198,7 +197,7 @@ class Parser : public NonCopyable
198197
const char* msg, va_list var_args);
199198

200199
_xmlParserCtxt* context_;
201-
std::exception_ptr exception_ptr_;
200+
std::unique_ptr<exception> exception_;
202201

203202
private:
204203
struct Impl;

0 commit comments

Comments
 (0)