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

我正在使用keybase(用于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()的调用,它将返回-1并将errno设置为EINTR (我没有尝试过这样,所以它可能不完美……):

 #include  #include  #include  #include  // 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已重新启动系统调用。