我正在使用管道在Gnu / Linux上的两个进程之间进行通信。接收端关闭管道,而发送端仍在尝试发送数据。以下是一些模拟情况的代码。
#include <unistd.h>
#include <boost/asio.hpp>
int main()
{
int pipe_fds[2];
if( ::pipe(pipe_fds) != 0 ) return 1;
// close the receiving end
::close( pipe_fds[0] );
boost::asio::io_service io;
boost::asio::posix::stream_descriptor sd( io, pipe_fds[1] );
boost::system::error_code ec;
sd.write_some( boost::asio::buffer("blah"), ec );
return 0;
}
当我运行它时,我得到一个SIGPIPE;经典情况,我知道。但是,我发现boost::asio::error::basic_errors
的值为broken_pipe
。我希望在没有信号被提升的情况下返回error_code。
这可以在不为我的进程创建SIGPIPE处理程序的情况下完成吗?例如,我是否缺少boost :: asio的配置选项?也许会在实现中启用MSG_NOSIGNAL?
答案 0 :(得分:7)
如果您希望查看相应的SIGPIPE
error_code
代码和编译
#include <unistd.h>
#include <iostream>
#include <boost/asio.hpp>
int main( int argc, const char** argv )
{
bool ignore = false;
if ( argc > 1 && !strcmp(argv[1], "ignore") ) {
ignore = true;
}
std::cout << (ignore ? "" : "not ") << "ignoring SIGPIPE" << std::endl;
if ( ignore ) {
struct sigaction sa;
std::memset( &sa, 0, sizeof(sa) );
sa.sa_handler = SIG_IGN;
int res = sigaction( SIGPIPE, &sa, NULL);
assert( res == 0 );
}
int pipe_fds[2];
if( ::pipe(pipe_fds) != 0 ) return 1;
// close the receiving end
::close( pipe_fds[0] );
boost::asio::io_service io;
boost::asio::posix::stream_descriptor sd( io, pipe_fds[1] );
boost::system::error_code ec;
sd.write_some( boost::asio::buffer("blah"), ec );
if ( ec ) {
std::cerr << boost::system::system_error(ec).what() << std::endl;
} else {
std::cout << "success" << std::endl;
}
return 0;
}
samjmill@bgqfen7 ~> g++ pipe.cc -lboost_system -lboost_thread-mt
samjmill@bgqfen7 ~>
运行
samm@macmini ~> ./a.out
not ignoring SIGPIPE
samm@macmini ~> echo $?
141
samm@macmini ~> ./a.out ignore
ignoring SIGPIPE
Broken pipe
samm@macmini ~>
此行为的基本原理在write(2)
man page
<强> EPIPE 强>
fd连接到读取端关闭的管道或插座。什么时候 这种情况发生在写入过程中也会收到SIGPIPE信号。 (因此,只有程序捕获时才会看到写返回值, 阻止或忽略此信号。)
我强调了。
答案 1 :(得分:3)
当管道的一端未连接时,操作系统会生成SIGPIPE - 您无法使用boost :: asio真正阻止它。然而,你可以简单地忽略信号,其余的应该自己处理。
答案 2 :(得分:2)
signal_init
已在文件boost/asio/detail/signal_init.hpp