MuntashirAkon/AppManager · error

ClosedChannelException

Error message

ClosedChannelException

What it means

OpenFile wraps a native file descriptor with synchronized operations (lseek, size, ftruncate, sync, etc.). Internal ensureOpen() checks that fd is still non-null; once close() has been called, fd is nulled and any subsequent operation throws ClosedChannelException, mirroring java.nio channels closed-state semantics.

Source

Thrown at libcore/io/src/main/java/io/github/muntashirakon/io/OpenFile.java:51

    private ByteBuffer buf;
    private StructStat st;

    private ByteBuffer getBuf() {
        if (buf == null)
            buf = ByteBuffer.allocateDirect(FileSystemService.PIPE_CAPACITY);
        buf.clear();
        return buf;
    }

    private StructStat getStat() throws ErrnoException {
        if (st == null)
            st = Os.fstat(fd);
        return st;
    }

    private void ensureOpen() throws ClosedChannelException {
        if (fd == null)
            throw new ClosedChannelException();
    }

    @Override
    synchronized public void close() {
        if (fd != null) {
            try {
                Os.close(fd);
            } catch (ErrnoException ignored) {
            }
            fd = null;
        }
        if (read != null) {
            try {
                Os.close(read);
            } catch (ErrnoException ignored) {
            }
            read = null;
        }

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Catch ClosedChannelException and reopen the file via FileSystemManager before retrying the operation
  2. Guard usage so no operation occurs after close (lifecycle management, single owner thread)
  3. Synchronize usage with close (the methods are synchronized; ensure the same monitor/lifecycle governs both)

Example fix

// before
openFile.close();
openFile.size(); // ClosedChannelException
// after
openFile.close();
if (!openFileClosed) { // or reopen instead
    OpenFile reopened = fm.openFile(path, "r");
    long sz = reopened.size();
}
Defensive patterns

Strategy: try-catch

Try / catch

try { long sz = openFile.size(); } catch (ClosedChannelException e) { openFile = fm.openFile(path, mode); sz = openFile.size(); }

Prevention

When it happens

Trigger: Calling lseek(), size(), ftruncate(), sync() (or anything else routed through ensureOpen) after close() on the same OpenFile; concurrent close from another thread while an operation is in flight; using an OpenFile returned from a remote manager whose file was closed remotely.

Common situations: try-with-resources or explicit close followed by lingering references still used; races between a close in a cleanup path and a read/write worker; reopening expectations after process restart without reacquiring the OpenFile.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/80e59679e202d5b5. Report an issue: GitHub.