SIGPIPE it's user problem

This commit is contained in:
Timofey Khoruzhii 2022-10-28 23:22:03 +03:00
parent d892676121
commit ec465d2dc7
4 changed files with 5 additions and 98 deletions

View file

@ -12,28 +12,18 @@ class Shell {
public: public:
Shell(const std::string& shell = "bash"); Shell(const std::string& shell = "bash");
void Execute(const std::string& command) { void Execute(const std::string& command);
#if defined(SIGPIPE_ALWAYS_IGNORE)
ExecuteImpl(command, false);
#else
ExecuteImpl(command, true);
#endif
}
int GetExitCodeLastCommand(); int GetExitCodeLastCommand();
~Shell() { ~Shell() {
#if defined(SIGPIPE_ALWAYS_IGNORE) Destroy();
Destroy(false);
#else
Destroy(true);
#endif
} }
private: private:
void ExecuteImpl(const std::string& command, bool need_ignore_sigpipe); void ExecuteImpl(const std::string& command, bool need_ignore_sigpipe);
void Destroy(bool need_ignore_sigpipe); void Destroy();
void MakeUniqueDirectory(); void MakeUniqueDirectory();
void MakeFifoFile(); void MakeFifoFile();

View file

@ -1,9 +0,0 @@
#pragma once
struct SigpipeState {
bool sigpipe_unblock = false;
};
bool IgnoreSigpipe();
void UnignoreSigpipe();

View file

@ -1,5 +1,4 @@
#include <cppshell/shell.hpp> #include <cppshell/shell.hpp>
#include <cppshell/utils/signals.hpp>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
@ -56,16 +55,8 @@ void Shell::MakeFifoFile() {
} }
} }
void Shell::ExecuteImpl(const std::string& command, bool need_ignore_sigpipe) { void Shell::Execute(const std::string& command) {
if (need_ignore_sigpipe) {
IgnoreSigpipe();
}
command_transmission_ << command << std::endl; command_transmission_ << command << std::endl;
if (need_ignore_sigpipe) {
UnignoreSigpipe();
}
} }
int Shell::GetExitCodeLastCommand() { int Shell::GetExitCodeLastCommand() {
@ -77,19 +68,11 @@ int Shell::GetExitCodeLastCommand() {
return result; return result;
} }
void Shell::Destroy(bool need_ignore_sigpipe) { void Shell::Destroy() {
Execute("exit"); Execute("exit");
if (need_ignore_sigpipe) {
IgnoreSigpipe();
}
command_transmission_.close(); command_transmission_.close();
if (need_ignore_sigpipe) {
UnignoreSigpipe();
}
waitpid(pid_shell_process_, 0, 0); waitpid(pid_shell_process_, 0, 0);
unlink(command_transmission_file_.data()); unlink(command_transmission_file_.data());

View file

@ -1,57 +0,0 @@
#include <cppshell/utils/signals.hpp>
#include <csignal>
#include <cerrno>
#if !defined(__APPLE__)
thread_local SigpipeState global_state;
#endif
bool IgnoreSigpipe() {
#if !defined(__APPLE__)
sigset_t pending;
sigemptyset(&pending);
sigpending(&pending);
bool sigpipe_pending = sigismember(&pending, SIGPIPE);
if (!sigpipe_pending) {
sigset_t sigpipe_mask;
sigemptyset(&sigpipe_mask);
sigaddset(&sigpipe_mask, SIGPIPE);
sigset_t blocked;
sigemptyset(&blocked);
pthread_sigmask(SIG_BLOCK, &sigpipe_mask, &blocked);
global_state.sigpipe_unblock = !sigismember(&blocked, SIGPIPE);
return true;
}
return false;
#endif
return false;
}
void UnignoreSigpipe() {
#if !defined(__APPLE__)
sigset_t pending;
sigemptyset(&pending);
sigpending(&pending);
bool sigpipe_pending = sigismember(&pending, SIGPIPE);
sigset_t sigpipe_mask;
sigemptyset(&sigpipe_mask);
sigaddset(&sigpipe_mask, SIGPIPE);
if (sigpipe_pending) {
const struct timespec nowait = {0, 0};
while (sigtimedwait(&sigpipe_mask, NULL, &nowait) == -1 && errno == EINTR) {
}
}
if (global_state.sigpipe_unblock) {
pthread_sigmask(SIG_UNBLOCK, &sigpipe_mask, NULL);
}
#endif
}