polybar-dwm/include/utils/file.hpp
Patrick Ziegler 444120e664
script: Fix concurrency issues (#2518)
Fixes #1978

* Move tail and non-tail handler to method

Defining them in the constructor is ugly.

* script: Iterate over defined actions instead of fixed list

* Separate running logic and lock m_output

* Include POLYBAR_FLAGS in linker flags

* Stop using m_prev in script_runner

* Join module threads in stop function

Joining in the destructor may lead to UB because the subclass is already
deconstructed but the threads may still require it to be around (e.g.
for calling any functions on the instance)

* Cleanup script module

* Update changelog

* Remove AfterReturn class

* Remove m_stopping from script module

* Fix polybar not reading the entire line from child process.

For every `readline` call we created a new fd_streambuf. This means once
`readline` returns, the streambuf is destructed and and pending data in
its temporary buffer discarded and we never actually read it.

* Remove unused includes
2021-10-03 01:27:11 +02:00

102 lines
2.2 KiB
C++

#pragma once
#include <streambuf>
#include "common.hpp"
POLYBAR_NS
class file_descriptor {
public:
explicit file_descriptor(const string& path, int flags = 0, bool autoclose = true);
explicit file_descriptor(int fd, bool autoclose = true);
~file_descriptor();
file_descriptor& operator=(const int);
explicit operator bool();
operator bool() const;
explicit operator int();
operator int() const;
protected:
void close();
private:
int m_fd{-1};
bool m_autoclose{true};
};
class fd_streambuf : public std::streambuf {
public:
using traits_type = std::streambuf::traits_type;
template <typename... Args>
explicit fd_streambuf(Args&&... args) : m_fd(forward<Args>(args)...) {
setg(m_in, m_in + BUFSIZE_IN, m_in + BUFSIZE_IN);
setp(m_out, m_out + BUFSIZE_OUT - 1);
}
~fd_streambuf();
explicit operator int();
operator int() const;
void open(int fd);
void close();
protected:
int sync() override;
int overflow(int c) override;
int underflow() override;
private:
static constexpr int BUFSIZE_OUT = 1024;
static constexpr int BUFSIZE_IN = 1024;
file_descriptor m_fd;
char m_out[BUFSIZE_OUT];
char m_in[BUFSIZE_IN];
};
template <typename StreamType>
class fd_stream : public StreamType {
public:
using type = fd_stream<StreamType>;
template <typename... Args>
explicit fd_stream(Args&&... args) : StreamType(nullptr), m_buf(forward<Args>(args)...) {
StreamType::rdbuf(&m_buf);
}
explicit operator int() {
return static_cast<const type&>(*this);
}
operator int() const {
return m_buf;
}
protected:
fd_streambuf m_buf;
};
namespace file_util {
bool exists(const string& filename);
bool is_file(const string& filename);
string pick(const vector<string>& filenames);
string contents(const string& filename);
void write_contents(const string& filename, const string& contents);
bool is_fifo(const string& filename);
vector<string> glob(string pattern);
const string expand(const string& path);
string get_config_path();
vector<string> list_files(const string& dirname);
template <typename... Args>
decltype(auto) make_file_descriptor(Args&&... args) {
return std::make_unique<file_descriptor>(forward<Args>(args)...);
}
} // namespace file_util
POLYBAR_NS_END