Project

General

Profile

Bug #10574

contextlocal cross-dependencies

Added by Constantin Asofiei 10 months ago. Updated 10 months ago.

Status:
New
Priority:
Urgent
Assignee:
-
Target version:
-
Start date:
Due date:
% Done:

0%

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

History

#2 Updated by Constantin Asofiei 10 months ago

There is a flow in FWD's context-local instantiation in cases where the current instance A is dependent on instance B, which needs context-local instance A. This can lead in creating different A's context-local instances cached in various places. An example is this stacktrace:

BufferManager.<init>() line: 815    
BufferManager.<init>(BufferManager) line: 813    
BufferManager$1.initialValue() line: 663    
BufferManager$1.initialValue() line: 1    
BufferManager$1(ContextLocal<T>).getImpl(boolean) line: 556    
BufferManager$1(ContextLocal<T>).get() line: 460    
BufferManager.get() line: 840    
ChangeBroker$ContextContainer.obtain() line: 1066    
ChangeBroker.get() line: 270    
BufferManager.<init>() line: 823    
BufferManager.<init>(BufferManager) line: 813    
BufferManager$1.initialValue() line: 663    
BufferManager$1.initialValue() line: 1    
BufferManager$1(ContextLocal<T>).getImpl(boolean) line: 556    
BufferManager$1(ContextLocal<T>).get() line: 460    
BufferManager.get() line: 840    
TransactionManager$ContextContainer.obtain() line: 11697    
TransactionManager.getTransactionHelper() line: 1803    
ProcedureManager$ContextContainer.obtain() line: 6611    
ProcedureManager.getProcedureHelper() line: 1140    
LogicalTerminal.init() line: 1696    
LogicalTerminal$1(ContextLocal<T>).initializeValue(T) line: 733    
LogicalTerminal$1(ContextLocal<T>).getImpl(boolean) line: 558    
LogicalTerminal$1(ContextLocal<T>).get() line: 460    
LogicalTerminal.locate() line: 12879    
LogicalTerminal.setClientMetrics(ClientMetrics) line: 14159    
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]    
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62    
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43    
Method.invoke(Object, Object...) line: 498    
MethodInvoker.invoke(Object[]) line: 126    
Dispatcher.processInbound(InboundRequest, boolean, NetResource) line: 808    
Conversation.block() line: 418    
Conversation.run() line: 237    
Thread.run() line: 750 [local variables unavailable]    

This exact case is solved easily by 10574a/16164:

=== modified file 'src/com/goldencode/p2j/persist/BufferManager.java'
--- old/src/com/goldencode/p2j/persist/BufferManager.java       2025-07-07 12:09:34 +0000
+++ new/src/com/goldencode/p2j/persist/BufferManager.java       2025-09-15 18:16:03 +0000
@@ -541,6 +541,7 @@
 ** 134 TG  20250707          Added null check before adding the buffer into the pendingBufferClasses
 **                           dictionary. This should fix the NullPointerException when using classes
 **                           instances with buffer trigger blocks.
+** 135 CA  20250915          ChangeBroker needs to be initialized first, as is dependent on BufferManager.
 */

 /*
@@ -837,6 +838,7 @@
     */
    public static BufferManager get()
    {
+      ChangeBroker.get(); // this is dependent on BufferManager, so get this first
       BufferManager bm = context.get();
       if (bm.connMgr == null)
       {

This needs to end up in trunk ASAP, and in all customer branches.


In a separate branch, we need to:
  • add a fail-safe in ContextLocal so that the class having context-local state, that state can not be created twice (in the same FWD session). This needs to be an obvious abend. I'm not sure how this can be easily added, maybe introspecting the stacktrace.
  • run this with all projects to find any other cases of cross-dependencies
  • investigate a rework of ContextLocal so that the pending instance can somehow be saved/cached and even if there are cross-dependencies, they are resolved automatically. For some, we use a ContextContainer approach where the i.e. constructor for BufferManager would do nothing, and only after the context-local instance gets created and set, then the state for i.e. the BufferManager is actually initialized. Maybe we need to make the ContextContainer approach mandatory, and the constructor to be no-op; or maybe add a mandatory method to initialize the context-local instance, and the constructor to be mandatory a no-op.

#3 Updated by Alexandru Lungu 10 months ago

  • Priority changed from Normal to Urgent
  • reviewer Alexandru Lungu added

#4 Updated by Constantin Asofiei 10 months ago

  • Status changed from New to Merge Pending

I'll merge after 10483a.

#5 Updated by Constantin Asofiei 10 months ago

  • Status changed from Merge Pending to New

Branch 10574a was merged to trunk rev 16207 and archived.

What's left is to improve/refactor the ContextLocal feature to make these kind of errors impossible.

Also available in: Atom PDF