x-pipe
x-pipe copied to clipboard
[Potential Issue] Make sure no resource leak here
https://github.com/ctripcorp/x-pipe/blob/b175922e3cd4fb77bad4f821c9cf7f7c4e67731e/core/src/main/java/com/ctrip/xpipe/netty/filechannel/ReferenceFileRegion.java#L33
@LanternLee 最近在整理JVM的GC和锁机制问题,顺便复习下x-pipe中keeper的锁用法,看到这个地方可能存在有泄漏的问题(我不是很确定, 需要验证一下, 我最近事情比较多, 只能提个issue, 你们帮忙看一下了),父类里面的deallocate是这么写的
@Override
protected void deallocate() {
FileChannel file = this.file;
if (file == null) {
return;
}
this.file = null;
try {
file.close();
} catch (IOException e) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to close a file.", e);
}
}
}
这个file不是File类,而是一个file channel,在netty写出去之后,会调用 release
方法,在 io.netty.util.AbstractReferenceCounted
中,里面其实调用的就是dealloc的方法:
@Override
public boolean release() {
return release0(1);
}
@Override
public boolean release(int decrement) {
return release0(checkPositive(decrement, "decrement"));
}
private boolean release0(int decrement) {
int oldRef = refCntUpdater.getAndAdd(this, -decrement);
if (oldRef == decrement) {
deallocate();
return true;
} else if (oldRef < decrement || oldRef - decrement > oldRef) {
// Ensure we don't over-release, and avoid underflow.
refCntUpdater.getAndAdd(this, decrement);
throw new IllegalReferenceCountException(oldRef, -decrement);
}
return false;
}
回头看这个地方,filechannel在通过netty的channel写给下游的slave之后,只是看看是否关闭了 private ControllableFile file;
,而可能漏掉了FileChannel (FileChannel 从对象关系来说,是从ControllableFile这个父亲中,分出来的child)
在Linux的模型下,相当于父子进程, 父进程被关闭, 子进程没有关闭, 从而可能成为 僵尸进程或者是孤儿进程(这个知识点我不是很确定)