Multithreading problem with saxon:stream

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Multithreading problem with saxon:stream

Rademacher, Gunther
Is it supported to reuse a resettable Reader, after it has been partially read by a streaming XQuery?
 
The problem that I am facing can be described along the following code fragment:
 
        String query = "saxon:stream(doc('uriresolver:resolve')/x/y/z)";
        XQueryExecutable xqueryExecutable = xqueryCompiler.compile(query);
        XQueryEvaluator xqueryEvaluator = xqueryExecutable.load();
        final StreamSource source = new StreamSource(reader);
        xqueryEvaluator.setURIResolver(new URIResolver() {
          @Override
          public Source resolve(String href, String base) throws TransformerException {
            return source;
          }
        });
        XdmSequenceIterator iterator = xqueryEvaluator.iterator();
        for (int j = 0; j < 31; ++j) {
          iterator.next();
        }
        iterator.close();
        xqueryEvaluator.close();
 
It reads into the stream up to a certain point, then closes down the XQueryEvaluator. The intent is to then reset the Reader and reuse it for another pass.
 
However it turns out that invoking iterator() spawns a separate thread, which still may be actively accessing the Reader after both of the close() calls have completed, thus interfering with the Reader’s follow-up task.
 
Should not the extra thread be joined during close?
 
Can I do something different to enforce this, or would I have to give up this resettable Reader approach completely?
 
Thanks for any hints!
Gunther
 

Software AG – Sitz/Registered office: Uhlandstraße 12, 64297 Darmstadt, Germany – Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Eric Duffaut, Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com

------------------------------------------------------------------------------

_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help 
Reply | Threaded
Open this post in threaded view
|

Re: Multithreading problem with saxon:stream

Michael Kay

On 27 May 2015, at 17:23, Rademacher, Gunther <[hidden email]> wrote:

Is it supported to reuse a resettable Reader, after it has been partially read by a streaming XQuery?

The first issue that came to my mind was that Saxon might mark() the Reader, which would cause reset() to set it to read from somewhere other than the beginning. Looking at the code, I don’t think we ever do mark() a reader, but I’m not sure that we guarantee not to! At one stage I was considering this as a way of handling try/catch with streaming.
 
The problem that I am facing can be described along the following code fragment:
 
        String query = "saxon:stream(doc('uriresolver:resolve')/x/y/z)";
        XQueryExecutable xqueryExecutable = xqueryCompiler.compile(query);
        XQueryEvaluator xqueryEvaluator = xqueryExecutable.load();
        final StreamSource source = new StreamSource(reader);
        xqueryEvaluator.setURIResolver(new URIResolver() {
          @Override
          public Source resolve(String href, String base) throws TransformerException {
            return source;
          }
        });
        XdmSequenceIterator iterator = xqueryEvaluator.iterator();
        for (int j = 0; j < 31; ++j) {
          iterator.next();
        }
        iterator.close();
        xqueryEvaluator.close();

The call on xqueryEvaluator.close() does nothing, and you should not be calling it. The documentation says it’s there for use when an XQueryEvaluator is being used as the Destination of some other query or transformation, which is not the case here.

The call on iterator.close() does in fact attempt the kind of tidying up that you describe, but it does nothing other than mark the channel as closed unless the producer thread (the one that actually reads from the Reader) is waiting for the consumer (the thread in which the query executes), which in my experiment isn’t the case. What happens now is that the producer will discover that the channel has closed next time it attempts to communicate, and will then shut itself down in response, aborting the SAX parse by throwing an exception which is then silently ignored.

This design might not be perfect from your point of view, but it works, and I’m reluctant to change it because of the potential for other things to break.

I think that creating a new Reader (and a new StreamSource) would be safer.

Michael Kay
Saxonica

 
It reads into the stream up to a certain point, then closes down the XQueryEvaluator. The intent is to then reset the Reader and reuse it for another pass.
 
However it turns out that invoking iterator() spawns a separate thread, which still may be actively accessing the Reader after both of the close() calls have completed, thus interfering with the Reader’s follow-up task.
 
Should not the extra thread be joined during close?
 
Can I do something different to enforce this, or would I have to give up this resettable Reader approach completely?
 
Thanks for any hints!
Gunther
 

Software AG – Sitz/Registered office: Uhlandstraße 12, 64297 Darmstadt, Germany – Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Eric Duffaut, Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com
------------------------------------------------------------------------------
_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help


------------------------------------------------------------------------------

_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help 
Reply | Threaded
Open this post in threaded view
|

Re: Multithreading problem with saxon:stream

Rademacher, Gunther

Thank you for looking into this issue. Meanwhile I have been working on an alternative implementation.

 

My new approach eliminates the reset by using multiple readers, however makes outdated readers return -1 from read requests. This in turn causes the stale thread to run into a parsing error (which indeed is silently ignored).

 

While this works fine, that parsing exception is occasionally logged to System.out by StandardErrorListener’s logger, causing some unnecessary attention.

 

What would be the right way to suppress the logging? I have tried to use getErrorListener().setLogger(), and configuration.setLogger(), but no success.

 

Attached is a test that demonstrates the unwanted log. It depends on timing, but on my machine reliably shows log like this:

 

stale reader signals eof...

Error on line 3616 column 17

  SXXP0003: Error reported by XML parser: XML document structures must start and end within

  the same entity.

 

Thanks again for your advice.

Gunther

 

 

From: Michael Kay [mailto:[hidden email]]
Sent: 28 May 2015 20:37
To: Mailing list for the SAXON XSLT and XQuery processor
Subject: Re: [saxon] Multithreading problem with saxon:stream

 

 

On 27 May 2015, at 17:23, Rademacher, Gunther <[hidden email]> wrote:

 

Is it supported to reuse a resettable Reader, after it has been partially read by a streaming XQuery?

 

The first issue that came to my mind was that Saxon might mark() the Reader, which would cause reset() to set it to read from somewhere other than the beginning. Looking at the code, I don’t think we ever do mark() a reader, but I’m not sure that we guarantee not to! At one stage I was considering this as a way of handling try/catch with streaming.

 

The problem that I am facing can be described along the following code fragment:

 

        String query = "saxon:stream(doc('uriresolver:resolve')/x/y/z)";

        XQueryExecutable xqueryExecutable = xqueryCompiler.compile(query);

        XQueryEvaluator xqueryEvaluator = xqueryExecutable.load();

        final StreamSource source = new StreamSource(reader);

        xqueryEvaluator.setURIResolver(new URIResolver() {

          @Override

          public Source resolve(String href, String base) throws TransformerException {

            return source;

          }

        });

        XdmSequenceIterator iterator = xqueryEvaluator.iterator();

        for (int j = 0; j < 31; ++j) {

          iterator.next();

        }

        iterator.close();

        xqueryEvaluator.close();

 

The call on xqueryEvaluator.close() does nothing, and you should not be calling it. The documentation says it’s there for use when an XQueryEvaluator is being used as the Destination of some other query or transformation, which is not the case here.

 

The call on iterator.close() does in fact attempt the kind of tidying up that you describe, but it does nothing other than mark the channel as closed unless the producer thread (the one that actually reads from the Reader) is waiting for the consumer (the thread in which the query executes), which in my experiment isn’t the case. What happens now is that the producer will discover that the channel has closed next time it attempts to communicate, and will then shut itself down in response, aborting the SAX parse by throwing an exception which is then silently ignored.

 

This design might not be perfect from your point of view, but it works, and I’m reluctant to change it because of the potential for other things to break.

 

I think that creating a new Reader (and a new StreamSource) would be safer.

 

Michael Kay

Saxonica



 

It reads into the stream up to a certain point, then closes down the XQueryEvaluator. The intent is to then reset the Reader and reuse it for another pass.

 

However it turns out that invoking iterator() spawns a separate thread, which still may be actively accessing the Reader after both of the close() calls have completed, thus interfering with the Reader’s follow-up task.

 

Should not the extra thread be joined during close?

 

Can I do something different to enforce this, or would I have to give up this resettable Reader approach completely?

 

Thanks for any hints!

Gunther

 

 

Software AG – Sitz/Registered office: Uhlandstraße 12, 64297 Darmstadt, Germany – Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Eric Duffaut, Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com

------------------------------------------------------------------------------
_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help

 


------------------------------------------------------------------------------

_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help 

SpuriosErrorLog.java (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Multithreading problem with saxon:stream

Michael Kay
I’m not sure how useful this is to you, but if your main concern is to intercept the error messages from the parser, you can do it like this:

public void testMultiPassSaxonStreaming() throws Exception {
    Configuration configuration = new EnterpriseConfiguration();

    final Source source[] = new Source[]{null};
    configuration.setURIResolver(new URIResolver() {
        public Source resolve(String href, String base) throws TransformerException {
            return source[0];
        }
    });
    String query = "saxon:stream(doc('uriresolver:resolve')/song/chorus)";
    Processor processor = new Processor(configuration);
    XQueryExecutable xqueryExecutable = processor.newXQueryCompiler().compile(query);

    int nPasses = 0;
    try {
        ReaderFactory readerFactory = new ReaderFactory();
        for (int repetition = 0; repetition < 4; ++repetition)
            for (int nResults = 8; nResults < 4096; nResults <<= 2) {
                XQueryEvaluator xqueryEvaluator = xqueryExecutable.load();
                final Reader factoryReader = readerFactory.newReader();
                final Reader delayingReader = new Reader() {

                    @Override
                    public int read(char[] cbuf, int off, int len) throws IOException {
                        randomDelay();
                        return factoryReader.read(cbuf, off, len);
                    }

                    @Override
                    public void close() throws IOException {
                    }
                };
                XMLReader xmlReader = configuration.getSourceParser();
                xmlReader.setErrorHandler(new ErrorHandler() {
                    public void error(SAXParseException exception) throws SAXException {
                        System.err.println("E: " + exception.getMessage());
                    }

                    public void warning(SAXParseException exception) throws SAXException {
                        System.err.println("W: " + exception.getMessage());
                    }

                    public void fatalError(SAXParseException exception) throws SAXException {
                        System.err.println("F:" + exception.getMessage());
                    }
                });
                source[0] = new SAXSource(xmlReader, new InputSource(delayingReader));

                XdmSequenceIterator iterator = xqueryEvaluator.iterator();
                for (int i = 0; i < nResults; ++i) {
                    iterator.next();
                }
                ++nPasses;
                randomDelay();
                iterator.close();
            }
    } catch (Exception e) {
        throw new RuntimeException("caught exception after " + nPasses
            + " passes: " + e, e);
    } finally {
        System.err.println("done with " + nPasses + " passes");
    }

In my tests, the errors were all notified to the fatalError() method.

Configuration.getSourceParser() should handle reuse of parser instances for you.

> On 2 Jun 2015, at 18:29, Rademacher, Gunther <[hidden email]> wrote:
>
> Thank you for looking into this issue. Meanwhile I have been working on an alternative implementation.
>
>  
>
> My new approach eliminates the reset by using multiple readers, however makes outdated readers return -1 from read requests. This in turn causes the stalea parsing error (which indeed is silently ignored).
>
>  
>
> While this works fine, that parsing exception is occasionally logged to System.out by StandardErrorListener’s logger, causing some unnecessary attention.
>
>  
>
> What would be the right way to suppress the logging? I have tried to use getErrorListener().setLogger(), and configuration.setLogger(), but no success.
>
>  
>
> Attached is a test that demonstrates the unwanted log. It depends on timing, but on my machine reliably shows log like this:
>
>  
>
> stale reader signals eof...
>
> Error on line 3616 column 17
>
>   SXXP0003: Error reported by XML parser: XML document structures must start and end within
>
>   the same entity.
>
>  
>
> Thanks again for your advice.
>
> Gunther
>
>  
>
>  
>
> From: Michael Kay [mailto:[hidden email]]
> Sent: 28 May 2015 20:37
> To: Mailing list for the SAXON XSLT and XQuery processor
> Subject: Re: [saxon] Multithreading problem with saxon:stream
>
>  
>
>  
>
> On 27 May 2015, at 17:23, Rademacher, Gunther <[hidden email]> wrote:
>
>  
>
> Is it supported to reuse a resettable Reader, after it has been partially read by a streaming XQuery?
>
>  
>
> The first issue that came to my mind was that Saxon might mark() the Reader, which would cause reset() to set it to read from somewhere other than the beginning. Looking at the code, I don’t think we ever do mark() a reader, but I’m not
>
>
>  
>
> The problem that I am facing can be described along the following code fragment:
>
>  
>
>         String query = "saxon:stream(doc('uriresolver:resolve')/x/y/z)";
>
>         XQueryExecutable xqueryExecutable = xqueryCompiler.compile(query);
>
>         XQueryEvaluator xqueryEvaluator = xqueryExecutable.load();
>
>         final StreamSource source = new StreamSource(reader);
>
>         xqueryEvaluator.setURIResolver(new URIResolver() {
>
>           @Override
>
>           public Source resolve(String href, String base) throws TransformerException {
>
>             return source;
>
>           }
>
>         });
>
>         XdmSequenceIterator iterator = xqueryEvaluator.iterator();
>
>         for (int j = 0; j < 31; ++j) {
>
>           iterator.next();
>
>         }
>
>         iterator.close();
>
>         xqueryEvaluator.close();
>
>  
>
> The call on xqueryEvaluator.close() does nothing, and you should not be calling it. The documentation says it’s there for use when an XQueryEvaluator is beingother query or transformation, which is not the case here.
>
>  
>
> The call on iterator.close() does in fact attempt the kind of tidying up that you describe, but it does nothing other than mark the channel as closed unless the producer thread (the one that actually reads from the Reader) is waiting for
>
>  
>
> This design might not be perfect from your point of view, but it works, and I’m reluctant to change it because of the potential for other things to break.
>
>  
>
> I think that creating a new Reader (and a new StreamSource) would be safer.
>
>  
>
> Michael Kay
>
> Saxonica
>
>
>
>  
>
> It reads into the stream up to a certain point, then closes down the XQueryEvaluator. The intent is to then reset the Reader and reuse it for another pass.
>
>  
>
> However it turns out that invoking iterator() spawns a separate thread, which still may be actively accessing the Reader after both of the close() calls have completed,interfering with the Reader’s follow-up task.
>
>  
>
> Should not the extra thread be joined during close?
>
>  
>
> Can I do something different to enforce this, or would I have to give up this resettable Reader approach completely?
>
>  
>
> Thanks for any hints!
>
> Gunther
>
>  
>
>  
>
> Software AG – Sitz/Registered office: Uhlandstraße 12, 64297 Darmstadt, Germany – Registergericht/Commercial register: Bereczky - http://www.softwareag.com
>
> ------------------------------------------------------------------------------
> _______________________________________________
> saxon-help mailing list archived at http://saxon.markmail.org/
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/saxon-help
>
>  
>
> <SpuriosErrorLog.java>------------------------------------------------------------------------------
> _______________________________________________
> saxon-help mailing list archived at http://saxon.markmail.org/
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/saxon-help


------------------------------------------------------------------------------
_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help 
Reply | Threaded
Open this post in threaded view
|

Re: Multithreading problem with saxon:stream

Michael Kay

>
> Configuration.getSourceParser() should handle reuse of parser instances for you.

That’s not quite true. For parser reuse to work, you need to return a parser to the pool after use using

Configuration.reuseSourceParser()

which must only be done after the parsing is complete.

Michael Kay
Saxonica
------------------------------------------------------------------------------
_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help 
Reply | Threaded
Open this post in threaded view
|

Re: Multithreading problem with saxon:stream

Rademacher, Gunther
In reply to this post by Michael Kay
Thanks. That lets me intercept the message, but what I actually want here is suppress it from showing up on System.err. But after the parser's ErrorHandler has seen the message, it is still logged by a call to StandardLogger.error() with this call stack:

      StandardLogger(Logger).error(String) line: 45
      StandardErrorListener.fatalError(TransformerException) line: 298
      Sender.sendSAXSource(SAXSource, Receiver, ParseOptions) line: 457
      Sender.send(Source, Receiver, ParseOptions) line: 146
      DocumentFn.sendDoc(String, String, XPathContext, SourceLocator, Receiver, ParseOptions) line: 821
      Doc.sendDocument(XPathContext, Receiver) line: 271
      StreamingCopy.process(XPathContext) line: 331
      SequenceExchanger$EvaluationThread.run() line: 174
      Thread.run() line: 745

And it seems that I cannot affect the behaviour of the listener or its logger for this very context.

I did however find out that there is no such logging when I use a StAXSource. In that case, Sender.sendPullSource is on the stack, and that (in contrast to sendSAXSource) doesn't seem to be connected to the listener logic.

Using the StAXSource is fine, though, and it seems to solve my problem. Thank you very much for your help!

Best regards,
Gunther


-----Original Message-----
From: Michael Kay [mailto:[hidden email]]
Sent: 03 June 2015 13:41
To: Mailing list for the SAXON XSLT and XQuery processor
Subject: Re: [saxon] Multithreading problem with saxon:stream

I’m not sure how useful this is to you, but if your main concern is to intercept the error messages from the parser, you can do it like this:

public void testMultiPassSaxonStreaming() throws Exception {
    Configuration configuration = new EnterpriseConfiguration();

    final Source source[] = new Source[]{null};
    configuration.setURIResolver(new URIResolver() {
        public Source resolve(String href, String base) throws TransformerException {
            return source[0];
        }
    });
    String query = "saxon:stream(doc('uriresolver:resolve')/song/chorus)";
    Processor processor = new Processor(configuration);
    XQueryExecutable xqueryExecutable = processor.newXQueryCompiler().compile(query);

    int nPasses = 0;
    try {
        ReaderFactory readerFactory = new ReaderFactory();
        for (int repetition = 0; repetition < 4; ++repetition)
            for (int nResults = 8; nResults < 4096; nResults <<= 2) {
                XQueryEvaluator xqueryEvaluator = xqueryExecutable.load();
                final Reader factoryReader = readerFactory.newReader();
                final Reader delayingReader = new Reader() {

                    @Override
                    public int read(char[] cbuf, int off, int len) throws IOException {
                        randomDelay();
                        return factoryReader.read(cbuf, off, len);
                    }

                    @Override
                    public void close() throws IOException {
                    }
                };
                XMLReader xmlReader = configuration.getSourceParser();
                xmlReader.setErrorHandler(new ErrorHandler() {
                    public void error(SAXParseException exception) throws SAXException {
                        System.err.println("E: " + exception.getMessage());
                    }

                    public void warning(SAXParseException exception) throws SAXException {
                        System.err.println("W: " + exception.getMessage());
                    }

                    public void fatalError(SAXParseException exception) throws SAXException {
                        System.err.println("F:" + exception.getMessage());
                    }
                });
                source[0] = new SAXSource(xmlReader, new InputSource(delayingReader));

                XdmSequenceIterator iterator = xqueryEvaluator.iterator();
                for (int i = 0; i < nResults; ++i) {
                    iterator.next();
                }
                ++nPasses;
                randomDelay();
                iterator.close();
            }
    } catch (Exception e) {
        throw new RuntimeException("caught exception after " + nPasses
            + " passes: " + e, e);
    } finally {
        System.err.println("done with " + nPasses + " passes");
    }

In my tests, the errors were all notified to the fatalError() method.

Configuration.getSourceParser() should handle reuse of parser instances for you.

> On 2 Jun 2015, at 18:29, Rademacher, Gunther <[hidden email]> wrote:
>
> Thank you for looking into this issue. Meanwhile I have been working on an alternative implementation.
>
>
>
> My new approach eliminates the reset by using multiple readers, however makes outdated readers return -1 from read requests. This in turn causes the stalea parsing error (which indeed is silently ignored).
>
>
>
> While this works fine, that parsing exception is occasionally logged to System.out by StandardErrorListener’s logger, causing some unnecessary attention.
>
>
>
> What would be the right way to suppress the logging? I have tried to use getErrorListener().setLogger(), and configuration.setLogger(), but no success.
>
>
>
> Attached is a test that demonstrates the unwanted log. It depends on timing, but on my machine reliably shows log like this:
>
>
>
> stale reader signals eof...
>
> Error on line 3616 column 17
>
>   SXXP0003: Error reported by XML parser: XML document structures must
> start and end within
>
>   the same entity.
>
>
>
> Thanks again for your advice.
>
> Gunther
>
>
>
>
>
> From: Michael Kay [mailto:[hidden email]]
> Sent: 28 May 2015 20:37
> To: Mailing list for the SAXON XSLT and XQuery processor
> Subject: Re: [saxon] Multithreading problem with saxon:stream
>
>
>
>
>
> On 27 May 2015, at 17:23, Rademacher, Gunther <[hidden email]> wrote:
>
>
>
> Is it supported to reuse a resettable Reader, after it has been partially read by a streaming XQuery?
>
>
>
> The first issue that came to my mind was that Saxon might mark() the
> Reader, which would cause reset() to set it to read from somewhere
> other than the beginning. Looking at the code, I don’t think we ever
> do mark() a reader, but I’m not
>
>
>
>
> The problem that I am facing can be described along the following code fragment:
>
>
>
>         String query =
> "saxon:stream(doc('uriresolver:resolve')/x/y/z)";
>
>         XQueryExecutable xqueryExecutable =
> xqueryCompiler.compile(query);
>
>         XQueryEvaluator xqueryEvaluator = xqueryExecutable.load();
>
>         final StreamSource source = new StreamSource(reader);
>
>         xqueryEvaluator.setURIResolver(new URIResolver() {
>
>           @Override
>
>           public Source resolve(String href, String base) throws
> TransformerException {
>
>             return source;
>
>           }
>
>         });
>
>         XdmSequenceIterator iterator = xqueryEvaluator.iterator();
>
>         for (int j = 0; j < 31; ++j) {
>
>           iterator.next();
>
>         }
>
>         iterator.close();
>
>         xqueryEvaluator.close();
>
>
>
> The call on xqueryEvaluator.close() does nothing, and you should not be calling it. The documentation says it’s there for use when an XQueryEvaluator is beingother query or transformation, which is not the case here.
>
>
>
> The call on iterator.close() does in fact attempt the kind of tidying
> up that you describe, but it does nothing other than mark the channel
> as closed unless the producer thread (the one that actually reads from
> the Reader) is waiting for
>
>
>
> This design might not be perfect from your point of view, but it works, and I’m reluctant to change it because of the potential for other things to break.
>
>
>
> I think that creating a new Reader (and a new StreamSource) would be safer.
>
>
>
> Michael Kay
>
> Saxonica
>
>
>
>
>
> It reads into the stream up to a certain point, then closes down the XQueryEvaluator. The intent is to then reset the Reader and reuse it for another pass.
>
>
>
> However it turns out that invoking iterator() spawns a separate thread, which still may be actively accessing the Reader after both of the close() calls have completed,interfering with the Reader’s follow-up task.
>
>
>
> Should not the extra thread be joined during close?
>
>
>
> Can I do something different to enforce this, or would I have to give up this resettable Reader approach completely?
>
>
>
> Thanks for any hints!
>
> Gunther


Software AG – Sitz/Registered office: Uhlandstraße 12, 64297 Darmstadt, Germany – Registergericht/Commercial register: Darmstadt HRB 1562 - Vorstand/Management Board: Karl-Heinz Streibich (Vorsitzender/Chairman), Eric Duffaut, Dr. Wolfram Jost, Arnd Zinnhardt; - Aufsichtsratsvorsitzender/Chairman of the Supervisory Board: Dr. Andreas Bereczky - http://www.softwareag.com

------------------------------------------------------------------------------
_______________________________________________
saxon-help mailing list archived at http://saxon.markmail.org/
[hidden email]
https://lists.sourceforge.net/lists/listinfo/saxon-help