繁体   English   中英

boost :: iostreams :: copy - sink - ENOSPC(设备上没有剩余空间)错误处理

[英]boost::iostreams::copy - sink - ENOSPC (No space left on device) error handling

在下面的代码片段中,有没有办法处理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()的错误抛出。

是否可以在ofstream对象上设置适当的exceptions() 我尝试过ofs.exceptions(std::ios::badbit | std::ios::failbit)但它没有任何区别。

上面的代码是用GCC编译的,并在Linux上运行。 提升版本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

过滤器

允许过滤器传播临时失败通知:如果下游设备消耗或产生的字符数少于过滤器请求的字符数,并且因此过滤器无法满足读取或写入请求,则过滤器可能会返回一个值,指示输入或输出暂时不可用。 希望这种能力足以允许当前的Filter概念与异步和非阻塞i / o一起使用。 但是,为了对阻塞i / o有用,过滤器必须永远不会返回临时故障通知,除非它已从下游设备收到此类通知 通过声明过滤器必须保持阻塞来总结此要求。 请参阅阻止。

粗体 )通过将E_NOSPC条件转换为临时故障通知 ,看起来好像IOStreams违反了这个原则。


boost::iostreams::copy特殊情况下源和目标间接设备的情况。 在这种情况下,两者都是间接的。 现在,特殊情况将接收器包装在non_blocking_adaptor 我不知道为什么,这似乎与从同一文档页面中获得的以下一般建议相矛盾:

流和流缓冲区

虽然Boost.Iostreams过滤器和设备概念可以适应非阻塞i / o,但C ++标准库流和流缓冲接口不能,因为它们缺乏区分临时和永久失败以满足读或写请求的方法。 因此,非阻塞设备无法与模板流,stream_buffer,filtering_stream和filtering_streambuf一起正常工作。

我尝试用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);
}

也许您应该将此报告为开发人员/邮件列表中的错误。

我想我找到了解决这个问题的方法。 我所做的是根据这里文档制作我自己的接收器。

基本上是一个接收sink ,可以处理写入然后检查流的good状态。

struct safe_ofstream_sink
{
    typedef char char_type;
    typedef boost::iostreams::sink_tag category;

    std::ofstream& ofs;

    safe_ofstream_sink(std::ofstream& ofs) :
            ofs(ofs)
    {
    }

    std::streamsize write(const char* s, std::streamsize n)
    {
        ofs.write(s, n);
        if (!ofs)
            throw std::runtime_error("Failed writing to fstream");

        return n;
    }
};


boost::iostreams::filtering_streambuf<boost::iostreams::output> filters;
filters.push(boost::iostreams::bzip2_decompressor());
filters.push(safe_ofstream_sink(ofs));
boost::iostreams::copy(ifs, filters);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM