fix: use O_CLOEXEC to prevent fds from leaking through other threads