SIGPIPE it's user problem
This commit is contained in:
parent
d892676121
commit
ec465d2dc7
|
@ -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();
|
||||||
|
|
|
@ -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/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());
|
||||||
|
|
|
@ -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