statvfs可以在某些网络设备上阻止吗?该如何处理? [英] Can statvfs block on certain network devices? How to handle that case?

查看:166
本文介绍了statvfs可以在某些网络设备上阻止吗?该如何处理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用keybase(用于SSH和其他密钥的云基础数据存储),而今天,以某种方式,当我启动X-Windows时它并没有重新启动。

I am using keybase (a cloud base data store for your SSH and other keys) and today somehow it did not restart when I started X-Windows.

结果,命令 df (因此在我的代码中为 statvfs())将在告诉我

As a result, the command df (and thus statvfs() in my code) would just block after telling me that the transport was down.

$ df
df: '/home/alexis/"/home/alexis/.local/share/keybase/fs"': Transport endpoint is not connected
df: /run/user/1000/gvfs: Transport endpoint is not connected
_

提示会坐在那里,永远不会返回。

The prompt would sit there and never return.

我不在乎 df 此刻可能会卡住,但我想知道如何更新C ++代码以处理 statvfs()在我的应用程序中被阻止,因为那里是不可接受的。我只是看不到不使用信号就不会打断电话的方法(想到了SIGALRM)。

I don't care much that df would get stuck at the moment, but I'm wondering how I should update my C++ code to handle the case where statvfs() blocks in my application because that's not acceptable there. I just don't see a way to break out of that call without using a signal (SIGALRM comes to mind).

有没有更好的方法来处理这种情况?

Is there a better way to handle this case?

(注意:我的代码是C ++,尽管C解决方案应该可以正常工作,并且可能是必需的,因此可以使用两种语言进行标记。)

(Note: my code is in C++, although a C solution should work just fine and is likely what is required, hence the tagging with both languages.)

推荐答案

此代码将 statvfs()包装在设置警报的函数中中断通话。如果警报触发并中断对 -1 且errno设置为 EINTR > statvfs()(我没有尝试过,所以可能并不完美...):

This code will wrap statvfs() in a function that sets up an alarm to interrupt the call. It will return -1 with errno set to EINTR should the alarm fire and interrupt the call to statvfs() (I haven't tried this so it may not be perfect...):

#include <sigaction.h>
#include <sys/statvfs.h>
#include <unistd.h>
#include <string.h>

// alarm handler doesn't need to do anything
// other than simply exist
static void alarm_handler( int sig )
{
    return;
}

 .
 .
 .

// statvfs() with a timeout measured in seconds
// will return -1 with errno set to EINTR should
// it time out
int statvfs_try( const char *path, struct statvfs *s, unsigned int seconds )
{
    struct sigaction newact;
    struct sigaction oldact;

    // make sure they're entirely clear (yes I'm paranoid...)
    memset( &newact, 0, sizeof( newact ) );
    memset( &oldact, 0, sizeof( oldact) );

    sigemptyset( &newact.sa_mask );

    // note that does not have SA_RESTART set, so
    // statvfs should be interrupted on a signal
    // (hopefully your libc doesn't restart it...)
    newact.sa_flags = 0;
    newact.sa_handler = alarm_handler;
    sigaction( SIGALRM, &newact, &oldact );

    alarm( seconds );

    // clear errno
    errno = 0;
    int rc = statvfs( path, s );

    // save the errno value as alarm() and sigaction() might change it
    int save_errno = errno;

    // clear any alarm and reset the signal handler
    alarm( 0 );
    sigaction( SIGALRM, &oldact, NULL );

    errno = saved_errno;
    return( rc );
}

这也可能会使用一些错误检查,尤其是在 sigaction()调用,但是它已经足够长,已经可以生成滚动条了,所以我将其省略。

That could also use some error checking, especially on the sigaction() calls, but it's long enough to generate a scroll bar already, so I left that out.

如果找到了进程仍然停留在 statvfs()调用中,如果您在Linux上运行,请在 strace 和跟踪实际的系统调用。您应该看到对 statvfs()的调用,然后是一个警报信号,中断了 statvfs()的调用。如果看到对 statvfs()另一个调用,则表明您的 libc 已重新启动系统调用。

If you find your process remains stuck in statvfs() call, and if you're running on Linux, run your process under the strace and trace the actual system calls. You should see the call to statvfs(), then an alarm signal that interrupts the statvfs() call. If you see another call to statvfs(), that means your libc has restarted the system call.

这篇关于statvfs可以在某些网络设备上阻止吗?该如何处理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆