在下面的代码片段中,有没有办法处理 ENOSPC
?
#include <fstream>
#include <iostream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
// open input file stream of the bzip2 file
std::ifstream ifs("file.bz2");
// open output stream to the "full" device
// full device is a "utility-device" to check how applications handle ENOSPC
// more details in "man full"
std::ofstream ofs("/dev/full");
// Setup the iostreams filter
boost::iostreams::filtering_streambuf<boost::iostreams::output> filters;
filters.push(boost::iostreams::bzip2_decompressor());
filters.push(ofs);
// "run" the filter
boost::iostreams::copy(ifs, filters);
如果我对编译后的二进制文件执行
strace
,该代码似乎会使用相同的数据无限调用 writev()
并返回 ENOSPC
错误。writev(4, [{NULL, 0}, {"DATA DATA "..., 4096}], 2) = -1 ENOSPC (No space left on device)
如何处理此错误或将其作为
boost::iostreams::copy()
的错误抛出。是否可以在
exceptions()
对象上设置适当的 ofstream
?我试过 ofs.exceptions(std::ios::badbit | std::ios::failbit)
但它没有任何区别。上面的代码是用 GCC 编译并在 Linux 上运行的。 boost 版 1.55。
最佳答案
它陷入了 non_blocking_adaptor<Device>::write(...)
的无限循环中:
std::streamsize result = 0;
while (result < n) {
std::streamsize amt =
iostreams::write(device_, s + result, n - result);
result += amt;
}
return result;
iostream::write(device_, ...
不断返回 0(所以 n 保持 n,amt 和结果保持 0)。这似乎是 Boost IOstreams 中的一个错误。也许它是在添加对非阻塞(同步)IO 的初步支持时引入的。根据文档,这应该是一项正在进行的工作。
特别有启发性的是:http://www.boost.org/doc/libs/1_55_0/libs/iostreams/doc/guide/asynchronous.html
(我的粗体)看起来好像 IOStreams 通过将 E_NOSPC 条件转换为临时故障通知而违反了这一原则。
boost::iostreams::copy
特例是源和目标间接设备的情况。在这种情况下,两者都是间接的。现在,特殊情况将接收器包装在 non_blocking_adaptor
中。我不知道为什么,这似乎与来自同一文档页面的以下一般建议相矛盾:我尝试用
file_sink
和 file_source
替换文件,但没有任何变化。 :(这是我的简化测试用例,它仍然重现了问题:
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filtering_streambuf.hpp>
int main()
{
using namespace boost::iostreams;
file_source ifs("/dev/zero");
file_sink ofs("/dev/full");
filtering_streambuf<output> filters(ofs);
copy(ifs, filters);
}
也许您应该将此报告为开发人员/邮件列表的错误。