SIGPIPE it's user problem
This commit is contained in:
parent
d892676121
commit
ec465d2dc7
|
@ -12,28 +12,18 @@ class Shell {
|
|||
public:
|
||||
Shell(const std::string& shell = "bash");
|
||||
|
||||
void Execute(const std::string& command) {
|
||||
#if defined(SIGPIPE_ALWAYS_IGNORE)
|
||||
ExecuteImpl(command, false);
|
||||
#else
|
||||
ExecuteImpl(command, true);
|
||||
#endif
|
||||
}
|
||||
void Execute(const std::string& command);
|
||||
|
||||
int GetExitCodeLastCommand();
|
||||
|
||||
~Shell() {
|
||||
#if defined(SIGPIPE_ALWAYS_IGNORE)
|
||||
Destroy(false);
|
||||
#else
|
||||
Destroy(true);
|
||||
#endif
|
||||
Destroy();
|
||||
}
|
||||
|
||||
private:
|
||||
void ExecuteImpl(const std::string& command, bool need_ignore_sigpipe);
|
||||
|
||||
void Destroy(bool need_ignore_sigpipe);
|
||||
void Destroy();
|
||||
|
||||
void MakeUniqueDirectory();
|
||||
void MakeFifoFile();
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
struct SigpipeState {
|
||||
bool sigpipe_unblock = false;
|
||||
};
|
||||
|
||||
bool IgnoreSigpipe();
|
||||
void UnignoreSigpipe();
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
#include <cppshell/shell.hpp>
|
||||
#include <cppshell/utils/signals.hpp>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
@ -56,16 +55,8 @@ void Shell::MakeFifoFile() {
|
|||
}
|
||||
}
|
||||
|
||||
void Shell::ExecuteImpl(const std::string& command, bool need_ignore_sigpipe) {
|
||||
if (need_ignore_sigpipe) {
|
||||
IgnoreSigpipe();
|
||||
}
|
||||
|
||||
void Shell::Execute(const std::string& command) {
|
||||
command_transmission_ << command << std::endl;
|
||||
|
||||
if (need_ignore_sigpipe) {
|
||||
UnignoreSigpipe();
|
||||
}
|
||||
}
|
||||
|
||||
int Shell::GetExitCodeLastCommand() {
|
||||
|
@ -77,19 +68,11 @@ int Shell::GetExitCodeLastCommand() {
|
|||
return result;
|
||||
}
|
||||
|
||||
void Shell::Destroy(bool need_ignore_sigpipe) {
|
||||
void Shell::Destroy() {
|
||||
Execute("exit");
|
||||
|
||||
if (need_ignore_sigpipe) {
|
||||
IgnoreSigpipe();
|
||||
}
|
||||
|
||||
command_transmission_.close();
|
||||
|
||||
if (need_ignore_sigpipe) {
|
||||
UnignoreSigpipe();
|
||||
}
|
||||
|
||||
waitpid(pid_shell_process_, 0, 0);
|
||||
|
||||
unlink(command_transmission_file_.data());
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in a new issue