codingapi / codingapi/tx-lcn

LCN debug time out, occur NullPointException and lock db record.

オープン
#464 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
Java
スター
4.2k
フォーク
1.4k
PR マージ指標
30日以内にマージされた PR はありません

説明

Although others also meet the similar situation, the exception seems not same.

### 1. Bug Description
When I debug in LCN model, it throw the "dtx timeout" LCNBusinessException. And when it catch the exception and handle, NullPointException is thrown in the handler logic.
What's more, it also lock the table dbs.
If I really run in timeout situation, I think NullPointException will be thrown as well.

### 2. Environment:
- JDK version: 1.8
- OS: window 10
- TX-LCN version: 5.0.0.RELEASE
- Others:

### 3. Exception Stacktrace
```
java.lang.NullPointerException: null
at com.codingapi.txlcn.tc.core.checking.DefaultDTXExceptionHandler.handleNotifyGroupBusinessException(DefaultDTXExceptionHandler.java:97)
at com.codingapi.txlcn.tc.core.template.TransactionControlTemplate.notifyGroup(TransactionControlTemplate.java:159)
at com.codingapi.txlcn.tc.core.transaction.lcn.control.LcnStartingTransaction.postBusinessCode(LcnStartingTransaction.java:65)
at com.codingapi.txlcn.tc.core.DTXServiceExecutor.transactionRunning(DTXServiceExecutor.java:109)
at com.codingapi.txlcn.tc.aspect.weave.DTXLogicWeaver.runTransaction(DTXLogicWeaver.java:95)
at com.codingapi.txlcn.tc.aspect.TransactionAspect.runWithLcnTransaction(TransactionAspect.java:93)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
```

### 4. Code
TransactionControlTemplate.java
```
public void notifyGroup(String groupId, String unitId, String transactionType, int state) {
try {
this.txLogger.transactionInfo(groupId, unitId, "notify group > {} > groupId: {xid}, unitId: {uid}, state: {}.", new Object[]{transactionType, state});
if (this.globalContext.isDTXTimeout()) {
throw new LcnBusinessException("dtx timeout.");
}

this.reliableMessenger.notifyGroup(groupId, state);
this.transactionCleanTemplate.clean(groupId, unitId, transactionType, state);
log.debug("{} > close transaction group.", transactionType);
} catch (TransactionClearException var6) {
log.error("clear exception", var6);
this.txLogger.trace(groupId, unitId, "Transaction Error", "clean transaction fail.", new Object[0]);
} catch (RpcException var7) {
this.dtxExceptionHandler.handleNotifyGroupMessageException(Arrays.asList(groupId, state, unitId, transactionType), var7);
} catch (LcnBusinessException var8) {
this.dtxExceptionHandler.handleNotifyGroupBusinessException(Arrays.asList(groupId, state, unitId, transactionType), var8.getCause());
}

this.txLogger.transactionInfo(groupId, unitId, "notify group exception state %d.", new Object[]{state});
}
```
DefaultDTXExceptionHandler.java
```
public void handleNotifyGroupBusinessException(Object params, Throwable ex) {
List paramList = (List)params;
String groupId = (String)paramList.get(0);
int state = (Integer)paramList.get(1);
String unitId = (String)paramList.get(2);
String transactionType = (String)paramList.get(3);

/*
* need to validate the ex whether is null
*/

if (ex instanceof UserRollbackException) {
state = 0;
}

if (ex.getCause() != null && ex.getCause() instanceof UserRollbackException) {
state = 0;
}

try {
this.transactionCleanTemplate.clean(groupId, unitId, transactionType, state);
} catch (TransactionClearException var9) {
log.error("{} > clean transaction error.", transactionType);
}
}
```

### 5. Tour Idea
Do a validation in DefaultDTXExceptionHandler.handleNotifyGroupBusinessException, validate whether the ex is null at first. Also need the validation in the similar code.

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

調査の方向性

Start with DefaultDTXExceptionHandler.handleNotifyGroupBusinessException and the call from TransactionControlTemplate.notifyGroup, where the timeout exception's cause is passed in. Review the similar exception-handling code mentioned in the issue. Done means timeout handling no longer dereferences a null cause and the transaction cleanup path remains protected from the reported NullPointerException.

索引モデルが issue の本文から書いたものです。

評価

技術スタック
java
領域
distributed-systems
issue の種類
バグ
難易度
2/5
見積もり時間
1〜3時間
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
45/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。