Summary
While working on #780, I was tracing the resource lifecycle in the IonFactory parser construction paths and noticed a separate issue with IOContext ownership.
For File/Path parser construction, IonFactory first creates an IOContext for the original input and uses it during input decoration.
Later, _createParser(..., InputStream) creates an IonReader and replaces the original context with a new one:
IonReader ion = _system.newReader(in);
ioCtxt = _createContext(_createContentReference(ion), true);
I checked #325, and the second IOContext appears to be intentional: it makes the IonReader the resource managed by the parser, so closing the parser also closes the IonReader.
However, the first IOContext has already acquired its own BufferRecycler. Once ioCtxt is replaced, the resulting IonParser only retains the second context, and the first context no longer appears to have an owner responsible for releasing it.
The lifecycle looks roughly like:
initial IOContext
↓
input decoration
↓
IonReader created
↓
second IOContext created for IonReader
↓
IonParser owns second IOContext
↓
parser.close()
↓
second IOContext released
initial IOContext remains unreleased
Unlike #780, this does not appear to be limited to failed construction. The initial IOContext may remain unreleased even when parser construction succeeds and the parser is later closed normally.
This may also affect other parser overloads that create an initial IOContext before going through the same IonReader construction path.
Expected behavior
When ownership moves from the initial input context to the IonReader-based context, the initial IOContext should also have its lifecycle completed so that its BufferRecycler lease is returned, while preserving the intended resource management of the IonReader.
I noticed this while addressing #780, but since this also affects successful parser construction, I think it is better handled as a separate lifecycle issue.
Summary
While working on #780, I was tracing the resource lifecycle in the
IonFactoryparser construction paths and noticed a separate issue withIOContextownership.For
File/Pathparser construction,IonFactoryfirst creates anIOContextfor the original input and uses it during input decoration.Later,
_createParser(..., InputStream)creates anIonReaderand replaces the original context with a new one:I checked #325, and the second
IOContextappears to be intentional: it makes theIonReaderthe resource managed by the parser, so closing the parser also closes theIonReader.However, the first
IOContexthas already acquired its ownBufferRecycler. OnceioCtxtis replaced, the resultingIonParseronly retains the second context, and the first context no longer appears to have an owner responsible for releasing it.The lifecycle looks roughly like:
Unlike #780, this does not appear to be limited to failed construction. The initial
IOContextmay remain unreleased even when parser construction succeeds and the parser is later closed normally.This may also affect other parser overloads that create an initial
IOContextbefore going through the sameIonReaderconstruction path.Expected behavior
When ownership moves from the initial input context to the
IonReader-based context, the initialIOContextshould also have its lifecycle completed so that itsBufferRecyclerlease is returned, while preserving the intended resource management of theIonReader.I noticed this while addressing #780, but since this also affects successful parser construction, I think it is better handled as a separate lifecycle issue.