I took a quick look at the public NITF schema yesterday, and the potential
there for unparser deadlocks is large. There is simply a bunch of nested
stored-length stuff going on in that format.

I think a test data XML for unparsing which has one or more of every kind
of element and sub-element in that schema is needed or we won't know if
we've found them all.

I recently created online example DFDL schemas that illustrate the
technique for avoiding these sorts of length-field-related circularities,
which is this:

   - For any element with lengthKind explicit and an expression that uses
   prior fields, that element must have complex type, and a single element
   child with dfdl:lengthKind 'implcit'.
   - This gives you two elements. The outer has its length computed from an
   expression, and the inner has its length rolled up from what is inside it.
   - OutputValueCalc expressions always want to refer to this inner
   element, not the outer one with the length expression.

The examples are:
https://github.com/DFDLSchemas/envelope-payload and
https://github.com/DFDLSchemas/tcpMessage

On Thu, Feb 15, 2024 at 3:49 PM Lara Blatchford <
lara.blatchf...@nteligen.com> wrote:

> Steve - thanks for this suggestion, it did the trick.  I see that the
> outputValueCalc in question is commented out in the latest version of the
> schema, is this issue avoided by other schema changes in that version?  I
> don't have easy access to get the latest version and try it, but I wanted
> to make sure an issue didn't need to be entered against the latest.
>
> Thanks again for your help,
> Lara
>
> -----Original Message-----
> From: Steve Lawrence <slawre...@apache.org>
> Sent: Wednesday, February 14, 2024 3:21 PM
> To: users@daffodil.apache.org
> Subject: Re: circular deadlock on NITF unparse
>
> This looks like a schema bug, and there are circular deadlocks. One common
> way to fix this issue is to break up an outputCalc expression so that
> instead of calculating the length of an element, you calculate the length
> of its children and add them together. This makes for a more complicated
> expression, but often times avoids circular references. In this particular
> case the dfdl:outputCalc property on the
> DataExtensionSegmentLengths/DataLength element can be changed from this:
>
>
>    dfdl:outputValueCalc="{
>
> dfdl:valueLength(../../../DataExtensionSegment[dfdl:occursIndex()]/Data,
> 'bytes')
>    }
>
> To this:
>
>    dfdl:outputValueCalc="{
>      if
>
> (fn:exists(../../../DataExtensionSegment[dfdl:occursIndex()]/Data/nitf:TaggedRecordExtensions))
>      then
>
> dfdl:valueLength(../../../DataExtensionSegment[dfdl:occursIndex()]/Data/nitf:TaggedRecordExtensions,
> 'bytes')
>      else
>
> dfdl:valueLength(../../../DataExtensionSegment[dfdl:occursIndex()]/Data/DESUserDefinedData,
> 'bytes')
>    }
>
> So instead of evaluating the length of just the Data element, it is
> changed to get the length of the TaggedRecordExtensions element or the
> DESUserDefinedData element depending on which one exists (since they are in
> a choice).
>
> You can see we do similar things to avoid deadlocks when calculating the
> lengths of various HeaderLength elements in the schema.
>
>
> On 2024-02-14 02:33 PM, Lara Blatchford wrote:
> > I’m using an older version of the NITF schema from github (attached) and
> > can parse the attached NITF file successfully.  On unparse I get the
> > circular deadlock error below.  I’m using Daffodil 3.5.0.
> >
> > How can I determine whether this is an issue with the data itself or a
> > bug in Daffodil as I see other open issues regarding circular deadlocks?
> >
> > Runtime Schema Definition Error: Expressions/Unparsers are circularly
> > deadlocked (mutually defined):  - target length for Data expr
> > <EvaluatableExpression eName='DataExtensionSegment/Data' expr='{
> > ../../Header/DataExtensionSegmentLengths[dfdl:occursIndex()]/DataLength
> > }' />  - target length for DESUserDefinedData expr
> > <EvaluatableExpression
> > eName='DataExtensionSegment/Data/DESUserDefinedData' expr='{
> >
> ../../../Header/DataExtensionSegmentLengths[dfdl:occursIndex()]/DataLength
> }' />  - SuspendableExpression(DataLength, expr={
> dfdl:valueLength(../../../DataExtensionSegment[dfdl:occursIndex()]/Data,
> 'bytes') }) Schema context: Data Location line 781 column 16 in
> nitf.dfdl.xsd Data location was preceding byte 1074
> >
> >   Thank you!
> >
> > Lara Blatchford
> >
> > Principal Engineer
> >
> > 240-341-1421
> >
>
>

Reply via email to