Project

General

Profile

Bug #10336

Issue on object deletion: java.lang.IllegalStateException

Added by Teodor Gorghe 12 months ago. Updated 9 months ago.

Status:
Test
Priority:
Normal
Assignee:
Target version:
-
Start date:
Due date:
% Done:

100%

billable:
No
vendor_id:
GCD
case_num:
version_reported:
version_resolved:
production:
No
env_name:
topics:

Related issues

Related to Base Language - Bug #10406: Wrong parameter mode for buffers passed to a constructor Test

History

#1 Updated by Teodor Gorghe 12 months ago

When a class has a static method call with buffer parameter, into a method/constructor, on DELETE OBJECT, FWD throws an java.lang.IllegalStateException:

Failures (1):
  FWD Test:tests.TestClassLoadByReference:testClassLoad
    MethodSource [className = 'com.goldencode.testcases.tests.TestClassLoadByReference', methodName = 'testClassLoad', methodParameterTypes = '']
    => java.lang.RuntimeException: invoke() of program tests.TestClassLoadByReference failed
       com.goldencode.p2j.util.ControlFlowOps.invokeError(ControlFlowOps.java:8547)
       com.goldencode.p2j.util.ControlFlowOps.invokeLegacyMethod(ControlFlowOps.java:5270)
       com.goldencode.p2j.util.ControlFlowOps.invokeLegacyMethod(ControlFlowOps.java:5158)
       com.goldencode.p2j.util.ObjectOps.invoke(ObjectOps.java:4912)
       com.goldencode.p2j.util.ObjectOps.invokeStandalone(ObjectOps.java:2717)
       [...]
     Caused by: java.lang.reflect.InvocationTargetException
       java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
       java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
       java.base/java.lang.reflect.Method.invoke(Method.java:569)
       com.goldencode.p2j.util.ControlFlowOps$InternalEntryCaller.invokeImpl(ControlFlowOps.java:9760)
       [...]
     Caused by: java.lang.IllegalStateException: Tracking for local/tstcasesdb/primary is unbalanced!
       com.goldencode.p2j.persist.TxWrapper$WorkArea.trackDatabase(TxWrapper.java:1158)
       com.goldencode.p2j.persist.TxWrapper$TxWrapperHelper.trackDatabase(TxWrapper.java:725)
       com.goldencode.p2j.persist.BufferManager.trackDatabase(BufferManager.java:3046)
       com.goldencode.p2j.persist.BufferManager.deregisterDynamicBuffer(BufferManager.java:1858)
       com.goldencode.p2j.persist.RecordBuffer.resourceDeleted(RecordBuffer.java:8046)
       [...]

Test case:

#3 Updated by Teodor Gorghe 12 months ago

  • Status changed from New to WIP
  • Assignee set to Teodor Gorghe

Created task branch 10336a.

#4 Updated by Teodor Gorghe 12 months ago

  • % Done changed from 0 to 10
From my investigation, BufferManager.trackDatabase is called 5 times:
  • RecordBuffer.defineAlias(Adaptivept1.Buf.class): add
  • RecordBuffer.openScope(btest): add
  • internalProcedure popScope from TestGetBuf: remove
  • ObjectOps.delete(obj) pdata.scopeables cleaning: remove
  • ObjectOps.delete(obj) pdata.staticResources BufferImpl resourceDeleteImpl: remove

#5 Updated by Teodor Gorghe 12 months ago

  • % Done changed from 10 to 100
  • Status changed from WIP to Review
  • reviewer Constantin Asofiei added

Committed revision 16067 on task branch 10336a:
- Fix for buffer passed as parameter on class instance/persistent procedure.

#6 Updated by Constantin Asofiei 12 months ago

Teodor, please upload the test with the .p programs.

#7 Updated by Teodor Gorghe 12 months ago

I have also tested this with some .p.
Take a look on this, which also failed before:

#8 Updated by Constantin Asofiei 12 months ago

Teodor, please test this change with the unit-test in question. In RecordBuffer:

   protected Boolean delayed = null;

   public void finished()
   {
      // calculate the 'delayed' flag only once
      if (delayed == null)
      {
         // need to be sure delayed is not polluted by a previous call
         delayed = !isDynamic() && txHelper.isExternalBlock();
      }

The root cause I think it was because the delayed flag was calculated more than once - this needs to be done only when the defining external procedure exits (persistent or not).

The current changes in 10336a are not OK.

#9 Updated by Teodor Gorghe 12 months ago

Committed revision 16068 on task branch 10336a:
- Reverted rev 16067. Modify delayed flag only once, according to #10336-8.

This solution is way better than what I have found.
I have tested this with the persistent procedure/class instance buffer and this fixed the issue.

I will test this change with some FWD converted applications to see if there are no other issues regarding this change.

#10 Updated by Constantin Asofiei 12 months ago

  • Status changed from Review to Internal Test

#11 Updated by Alexandru Lungu 12 months ago

  • Status changed from Internal Test to Merge Pending

Please merge 10336a to trunk after 10309a.

#12 Updated by Teodor Gorghe 12 months ago

  • Status changed from Merge Pending to Test

Branch 10336a was merged to trunk rev 16097 and archived.

#13 Updated by Șerban Bursuc 11 months ago

Revision 16097 is causing a regression in a customer application. I will revert 10336a to unfreeze a trunk delivery and then I will later post a stack trace with the error.

#14 Updated by Șerban Bursuc 11 months ago

Stack trace:

ErrorManager.displayError(String, boolean, String[], boolean, boolean) line: 3550    
ErrorManager.recordOrThrowError(int[], String[], boolean, boolean, boolean, boolean) line: 2037    
ErrorManager.recordOrThrowError(int[], String[], boolean, boolean, boolean) line: 1922    
ErrorManager.recordOrThrowError(int[], String[], boolean, boolean) line: 1891    
ErrorManager.recordOrThrowError(int, String, boolean) line: 1820    
ErrorManager.recordOrThrowError(int, String) line: 1799    
RecordBuffer.errorNotAvailable(String) line: 12656    
TemporaryBuffer(RecordBuffer).errorNotAvailable() line: 12679    
RecordBuffer$Handler.invoke(Object, Method, Object[]) line: 12992    
$__Proxy2017.get<redacted>(int) line: not available    
GeneratedMethodAccessor1198.invoke(Object, Object[]) line: not available    
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43    
Method.invoke(Object, Object...) line: 569    
Utils.invoke(Method, Object, Object...) line: 1787    
TemporaryBuffer$ReferenceProxy.invoke(Object, Method, Object[]) line: 9721    
$__Proxy2018.get<redacted>(int) line: not available    
$__Proxy2018.get<redacted>(NumberType) line: not available    

Doesn't look very verbose... will check the OE code for a testcase.

#15 Updated by Șerban Bursuc 11 months ago

Testcase is a bit difficult but from what I see there is a temp-table buffer reference and when the procedure that declares the temp-table using an .i file execute's function ends the temp-table is dereferenced and the entire temp-table becomes empty leading to the error. Before doing target.deleted() in TransactionManager.processFinalizables delayed is false but if we re-compute it it's true. In rev. 16097 this re-computation is skipped so finishedImpl is called but in trunk where it works worldScope is set.

I will try to have 2 procedures use an include file where a temp-table is declared, have the scope of one procedure end and see if the other procedure's temp-table still has records. This is my lead so far.

#16 Updated by Teodor Gorghe 11 months ago

Șerban Bursuc wrote:

Testcase is a bit difficult but from what I see there is a temp-table buffer reference and when the procedure that declares the temp-table using an .i file execute's function ends the temp-table is dereferenced and the entire temp-table becomes empty leading to the error. Before doing target.deleted() in TransactionManager.processFinalizables delayed is false but if we re-compute it it's true. In rev. 16097 this re-computation is skipped so finishedImpl is called but in trunk where it works worldScope is set.

I will try to have 2 procedures use an include file where a temp-table is declared, have the scope of one procedure end and see if the other procedure's temp-table still has records. This is my lead so far.

On preprocessing step, preprocessor include directives like .i what are you referring to, are replaced with actual .i preprocessor result. Please also look in .p.cache files. If the testcase is hard to reproduce, please tell me how to reproduce (in pm).

#17 Updated by Șerban Bursuc 11 months ago

Testcase:

proc1.p:

{table.i}

create tt.
tt.f1 = "a".

define variable hProc2 as handle.

run proc2.p persistent set hProc2 (input this-procedure).
run display-recs in hProc2.

proc2.p:

{table.i}

define input parameter hParent as handle.

procedure init:
    define parameter buffer ttB for tt.
    ttB.f1 = "c".
end procedure.

create tt.
tt.f1 = "b".
run init (buffer tt).

procedure display-recs:
    define variable msg as character.
    for each tt:
        message tt.f1.
        msg = tt.f1.
    end.

    if msg = "" then do:
        message "no records found! gg.".
    end.
end.

table.i:

define temp-table tt no-undo
field f1 as character.

This doesn't have anything to do with include files. I think 10336a was fixing a valid bug, if we check in proc1 after running the persistent set what records are in tt it's a, I think this is what Teodor was fixing (?), but in this case it looks like the buffer isn't cleared after the initial scope of proc2 ends, OE knows that another potential call in the same procedure can occur and it's keeping the modified "stale" value of the procedure for future use, that's why it sees c.

#18 Updated by Teodor Gorghe 11 months ago

Șerban Bursuc wrote:

Testcase:

proc1.p:
[...]

proc2.p:
[...]

table.i:
[...]

This doesn't have anything to do with include files. I think 10336a was fixing a valid bug, if we check in proc1 after running the persistent set what records are in tt it's a, I think this is what Teodor was fixing (?), but in this case it looks like the buffer isn't cleared after the initial scope of proc2 ends, OE knows that another potential call in the same procedure can occur and it's keeping the modified "stale" value of the procedure for future use, that's why it sees c.

Thanks!
I will tests this and I will rethink the solution, with this in mind.

#19 Updated by Teodor Gorghe 11 months ago

  • % Done changed from 100 to 20
  • Status changed from Test to WIP

Created task branch 10336b.

#20 Updated by Teodor Gorghe 11 months ago

  • Related to Bug #10406: Wrong parameter mode for buffers passed to a constructor added

#21 Updated by Teodor Gorghe 11 months ago

  • % Done changed from 20 to 100
  • Status changed from WIP to Review

Committed revision 16110 on task branch 10336b:
- Fixed regression from 10336a: deleted flag can be computed when the buffer is not worldScope.

#22 Updated by Constantin Asofiei 11 months ago

  • Status changed from Review to Internal Test

Please put this into testing.

#23 Updated by Constantin Asofiei 9 months ago

  • Status changed from Internal Test to Merge Pending

This can be merged after 10391a.

#24 Updated by Teodor Gorghe 9 months ago

  • Status changed from Merge Pending to Test

Branch 10336b was merged to trunk rev. 16230 and archived.

Also available in: Atom PDF