blob: 9c959b069c52dccee55fbfafceb1f939d0cd7915 [file]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Linux File specialization for streams created by popen.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC___SUPPORT_FILE_LINUX_POPEN_FILE_H
#define LLVM_LIBC_SRC___SUPPORT_FILE_LINUX_POPEN_FILE_H
#include "hdr/types/pid_t.h"
#include "src/__support/File/file.h"
#include "src/__support/File/file_mode.h"
#include "src/__support/File/linux/file.h"
#include "src/__support/macros/config.h"
#include "src/__support/threads/mutex.h"
namespace LIBC_NAMESPACE_DECL {
// A LinuxFile connected to a pipe to a child process created by popen. Open
// popen streams are kept on their own list, so that each new popen child can
// close the streams of earlier popen calls.
class PopenFile : public LinuxFile {
pid_t pid = -1;
PopenFile *popen_prev = nullptr;
PopenFile *popen_next = nullptr;
static PopenFile *popen_list;
static Mutex popen_list_lock;
// Removes |f| from the popen list, then closes and frees it like a
// LinuxFile. This does not wait for the child process.
static int popen_file_close(File *f);
public:
PopenFile(int file_descriptor, uint8_t *buffer, size_t buffer_size,
int buffer_mode, bool owned, FileMode mode)
: LinuxFile(file_descriptor, buffer, buffer_size, buffer_mode, owned,
mode, &popen_file_close) {}
pid_t get_pid() const { return pid; }
void set_pid(pid_t new_pid) { pid = new_pid; }
// The popen list lock must be held while calling the *_unlocked functions
// below. popen holds it from before forking until the new stream is on the
// list, so that the child sees a consistent list.
static void lock_popen_list() { popen_list_lock.lock(); }
static void unlock_popen_list() { popen_list_lock.unlock(); }
// Adds |f| to the popen list.
static void add_to_popen_list_unlocked(PopenFile *f);
// Closes the file descriptors of every stream on the popen list without
// freeing anything. This is meant to be called in a newly forked child.
static void close_popen_list_fds_unlocked();
};
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_FILE_LINUX_POPEN_FILE_H