summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2016-05-30 17:47:06 +0100
committerCaolán McNamara <caolanm@redhat.com>2016-05-30 20:46:30 +0100
commitbce5cdcc7f59da19c063205c6c79fc30874cb5ee (patch)
treeb4bd090d385e9d761f8d7ec7f47756b751e70c76
parente19be2e175e146152a08982e411b01ba8f0c2bb1 (diff)
Resolves: tdf#100057 force libxslt to give up when we cancel a transformation
we're already using libxslt internals, so using XSLT_STATE_STOPPED isn't an additional exposure This probably isn't all that useful to the original reporter in terms of importing useful data, but it does turn a hopeless situation into something that can be cancelled. Change-Id: I08e9a1dcd9ee78e1804faec500bbcca36a546988 (cherry picked from commit 2805adb0d3cf68d7def01a93bf07fb2e8121ec10)
-rw-r--r--filter/source/xsltfilter/LibXSLTTransformer.cxx26
-rw-r--r--filter/source/xsltfilter/LibXSLTTransformer.hxx69
2 files changed, 53 insertions, 42 deletions
diff --git a/filter/source/xsltfilter/LibXSLTTransformer.cxx b/filter/source/xsltfilter/LibXSLTTransformer.cxx
index 3dbe7a43ffb8..55f1920adae4 100644
--- a/filter/source/xsltfilter/LibXSLTTransformer.cxx
+++ b/filter/source/xsltfilter/LibXSLTTransformer.cxx
@@ -203,7 +203,8 @@ namespace XSLT
Reader::Reader(LibXSLTTransformer* transformer) :
Thread("LibXSLTTransformer"), m_transformer(transformer),
- m_readBuf(INPUT_BUFFER_SIZE), m_writeBuf(OUTPUT_BUFFER_SIZE)
+ m_readBuf(INPUT_BUFFER_SIZE), m_writeBuf(OUTPUT_BUFFER_SIZE),
+ m_tcontext(nullptr)
{
LIBXML_TEST_VERSION;
}
@@ -288,7 +289,6 @@ namespace XSLT
xsltStylesheetPtr styleSheet = xsltParseStylesheetFile(
reinterpret_cast<const xmlChar *>(m_transformer->getStyleSheetURL().getStr()));
xmlDocPtr result = nullptr;
- xsltTransformContextPtr tcontext = nullptr;
exsltRegisterAll();
registerExtensionModule();
#ifdef DEBUG_FILTER_LIBXSLTTRANSFORMER
@@ -298,11 +298,11 @@ namespace XSLT
std::unique_ptr<OleHandler> oh(new OleHandler(m_transformer->getComponentContext()));
if (styleSheet)
{
- tcontext = xsltNewTransformContext(styleSheet, doc);
- tcontext->_private = static_cast<void *> (oh.get());
- xsltQuoteUserParams(tcontext, &params[0]);
+ m_tcontext = xsltNewTransformContext(styleSheet, doc);
+ m_tcontext->_private = static_cast<void *> (oh.get());
+ xsltQuoteUserParams(m_tcontext, &params[0]);
result = xsltApplyStylesheetUser(styleSheet, doc, nullptr, nullptr, nullptr,
- tcontext);
+ m_tcontext);
}
if (result)
@@ -330,7 +330,8 @@ namespace XSLT
closeOutput();
oh.reset();
xsltFreeStylesheet(styleSheet);
- xsltFreeTransformContext(tcontext);
+ xsltFreeTransformContext(m_tcontext);
+ m_tcontext = nullptr;
xmlFreeDoc(doc);
xmlFreeDoc(result);
}
@@ -351,6 +352,16 @@ namespace XSLT
}
+ void Reader::forceStateStopped()
+ {
+ if (!m_tcontext)
+ return;
+ //tdf#100057 If we force a cancel, libxslt will of course just keep on going unless something
+ //tells it to stop. Here we force the stopped state so that libxslt will stop processing
+ //and so Reader::execute will complete and we can join cleanly
+ m_tcontext->state = XSLT_STATE_STOPPED;
+ }
+
Reader::~Reader()
{
}
@@ -455,6 +466,7 @@ namespace XSLT
if (m_Reader.is())
{
m_Reader->terminate();
+ m_Reader->forceStateStopped();
m_Reader->join();
}
m_Reader.clear();
diff --git a/filter/source/xsltfilter/LibXSLTTransformer.hxx b/filter/source/xsltfilter/LibXSLTTransformer.hxx
index d276018c0056..9c4485bb28b2 100644
--- a/filter/source/xsltfilter/LibXSLTTransformer.hxx
+++ b/filter/source/xsltfilter/LibXSLTTransformer.hxx
@@ -47,6 +47,36 @@ using ::std::map;
namespace XSLT
{
+ class LibXSLTTransformer;
+
+ /*
+ * Reader provides a worker thread to perform the actual transformation.
+ * It pipes the streams provided by a LibXSLTTransformer
+ * instance through libxslt.
+ */
+ class Reader : public salhelper::Thread
+ {
+ public:
+ Reader(LibXSLTTransformer* transformer);
+ int SAL_CALL read(char * buffer, int len);
+ int SAL_CALL write(const char * buffer, int len);
+ void forceStateStopped();
+ int SAL_CALL closeOutput();
+
+ private:
+ virtual ~Reader();
+
+ static const sal_Int32 OUTPUT_BUFFER_SIZE;
+ static const sal_Int32 INPUT_BUFFER_SIZE;
+ LibXSLTTransformer* m_transformer;
+ Sequence<sal_Int8> m_readBuf;
+ Sequence<sal_Int8> m_writeBuf;
+ xsltTransformContextPtr m_tcontext;
+
+ virtual void execute() override;
+ static void SAL_CALL registerExtensionModule();
+ };
+
/*
* LibXSLTTransformer provides an transforming pipe service to XSLTFilter.
*
@@ -85,13 +115,14 @@ namespace XSLT
::std::map<const char *, OString> m_parameters;
- rtl::Reference< salhelper::Thread > m_Reader;
+ rtl::Reference<Reader> m_Reader;
protected:
virtual ~LibXSLTTransformer() {
if (m_Reader.is()) {
- m_Reader->terminate();
- m_Reader->join();
+ m_Reader->terminate();
+ m_Reader->forceStateStopped();
+ m_Reader->join();
}
}
@@ -144,39 +175,7 @@ namespace XSLT
}
};
-
- /*
- * Reader provides a worker thread to perform the actual transformation.
- * It pipes the streams provided by a LibXSLTTransformer
- * instance through libxslt.
- */
- class Reader : public salhelper::Thread
- {
- public:
- Reader(LibXSLTTransformer* transformer);
- int SAL_CALL
- read(char * buffer, int len);
- int SAL_CALL
- write(const char * buffer, int len);
- int SAL_CALL
- closeOutput();
-
- private:
- virtual
- ~Reader();
-
- static const sal_Int32 OUTPUT_BUFFER_SIZE;
- static const sal_Int32 INPUT_BUFFER_SIZE;
- LibXSLTTransformer* m_transformer;
- Sequence<sal_Int8> m_readBuf;
- Sequence<sal_Int8> m_writeBuf;
-
- virtual void execute() override;
- static void SAL_CALL registerExtensionModule();
- };
-
}
-;
#endif // INCLUDED_FILTER_SOURCE_XSLTFILTER_LIBXSLTTRANSFORMER_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */