x-pipe icon indicating copy to clipboard operation
x-pipe copied to clipboard

[Potential Issue] Make sure no resource leak here

Open NickNYU opened this issue 3 years ago • 0 comments

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的模型下,相当于父子进程, 父进程被关闭, 子进程没有关闭, 从而可能成为 僵尸进程或者是孤儿进程(这个知识点我不是很确定)

NickNYU avatar Jan 28 '22 09:01 NickNYU