在下面的代码片段中,有没有办法处理 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_sinkfile_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);
}
也许您应该将此报告为开发人员/邮件列表的错误。

10-08 08:11