Locked Forever

std::mutex m;

std::vector<int> load(const char* path) {
    m.lock();
    std::FILE* f = std::fopen(path, "rb");
    auto data = parse(f);        // may throw std::runtime_error
    std::fclose(f);
    m.unlock();
    return data;
}

parse throws on a malformed file. What is the state of the process afterwards?

A

Only the lock is stuck: fclose is registered by fopen as an exit handler, so the stream is flushed and closed regardless.

B

The FILE* stays open and m stays locked, so the next call to load from any thread blocks forever.

C

Only the FILE* leaks: std::mutex releases itself during stack unwinding, the same way a lock_guard would.

D

Nothing leaks: the exception propagates out of load, and the runtime closes descriptors and releases locks acquired in the unwound frame.