在unix文件系统中使用带有popen的FILE描述符时崩溃

时间:2015-10-14 18:25:04

标签: c++ unix filesystems popen

我们有一段使用Flex和C风格FILE *描述符的遗留代码。为了支持将压缩文件读入Flex,我们使用

扩展了“开放”语义以打开gzip的文件。
FILE* file = popen("gzip -cd <filename>");

而不是fopen

我们最近遇到了一些问题,在unix文件系统上尝试这个问题(可能是在NetApp上使用NFS挂载的另一个文件系统)会导致整个代码流崩溃(segfault),我们看到的第一条消息是

  

gzip:stdout:Broken Pipe

和我们自己的崩溃框架。 如果我们获取文件并将其移动到运行进程的本地文件系统,则没有段错误,一切正常。

我们试图复制或修复什么?

  • 从内部测试NFS文件系统读取使用gzip / bzip2等压缩的文件
  • 验证是否可以打开目标文件
  • “打开”文件并读取几个字节以确保它可以通过此过程打开

所有这些都成功了,但我们仍然遇到了崩溃。

我们缺乏想法,可以使用一些建议。

Sam Appleton

1 个答案:

答案 0 :(得分:0)

当你测试它时,SIGPIPE有它的默认动作(杀死gzip进程)。当进程在您的客户端运行时,SIGPIPE被屏蔽。这是一个重现错误的最小程序:

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>

#define SZ 4096

void mask()
{
    struct sigaction sa;
    sa.sa_handler = SIG_IGN;
    sa.sa_flags = 0;
    if (-1 == sigaction(SIGPIPE, &sa, 0))
    {
        perror("sigaction");
        exit(1);
    }
}

int main(int argc, char ** argv)
{
    char buf[SZ];

#ifdef MASK
    mask();
#endif

    FILE * f = popen("gzip -dc foo.gz", "r");
    if (0 != fread(buf, SZ, 1, f))
    {
        fwrite(buf, SZ, 1, stdout);
    }

    fprintf(stderr, "%d\n", pclose(f));
}

这里有和没有MASK的输出:

$ gcc -o foo foo.c
$ gcc -DMASK -o foomask foo.c
$ /foo > /dev/null
13
$ /foomask > /dev/null 

gzip: stdout: Broken pipe
256
$

简而言之,它与NFS无关。那是一只红鲱鱼。