Can statvfs block on certain network devices? How to handle this business?

I use keybase (a cloud base data warehouse for your SSH and other keys), and today it somehow did not reboot when I started X-Windows.

As a result, the command df(and therefore statvfs()in my code) simply blocked, telling me that the transport is not working.

$ 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 request will sit and never return.

I don’t care what dfwould be stuck at the moment, but I wonder how I have to update my C ++ code to handle the case when it statvfs()blocks in my application, because this is unacceptable. I just don't see the possibility of escaping this call without using a signal (SIGALRM comes to mind).

Is there a better way to handle this case?

(Note: my code is in C ++, although the C solution should work fine and most likely requires, therefore, tagging in both languages.)

0
source share
1 answer

This code will wrap statvfs()in a function that sets an alarm to interrupt a call. It will return -1with errno set to EINTRif the alarm lights up and interrupts the call statvfs()(I have not tried this so that it is not 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 );
}

It may also use some error checking, especially on calls sigaction(), but it is long enough to generate a scrollbar already, so I left it.

, statvfs(), Linux, strace . statvfs(), , statvfs(). statvfs(), , libc .

+1

All Articles