statvfs 可以在某些网络设备上阻止吗?如何处理这种情况?



我正在使用密钥库(用于SSH和其他密钥的云基础数据存储),今天当我启动X-Windows时,它不知何故没有重新启动。

结果,命令df(因此在我的代码中statvfs())会在告诉我传输已关闭后阻止。

$ 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
_

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

我不太在乎df目前会卡住,但我想知道如何更新我的C++代码来处理应用程序中statvfs()块的情况,因为这在那里是不可接受的。我只是看不到在不使用信号的情况下摆脱该呼叫的方法(想到 SIGALRM)。

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

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

此代码将statvfs()包装在一个函数中,该函数设置警报以中断呼叫。 如果警报触发并中断对statvfs()的调用,它将返回 errno 设置为EINTR-1(我还没有尝试过这个,所以它可能并不完美......

#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()调用上,但它已经足够长,可以生成滚动条,所以我省略了它。

如果您发现您的进程仍然停滞在statvfs()调用中,并且如果您在 Linux 上运行,请在strace下运行您的进程并跟踪实际的系统调用。 您应该看到对statvfs()的调用,然后是中断statvfs()呼叫的警报信号。 如果您看到另一个statvfs()的调用,则表示您的libc已重新启动系统调用。

最新更新