NFS timeout problem [Archive] - C Board

PDA

View Full Version : NFS timeout problem


rotis23
10-20-2003, 08:56 AM
Hi All,

I have some code that is require to chdir(2) to a directory. If the chdir(2) fails, create it.

Now this directory is on an NFS mount. These are 'hard' linked!

If the remote NFS server is not running (for whatever reason), the code will hang on chdir. I've tried to use an alarm timeout around the chdir call, but this seems to be handled.

Does anyone suggest using select(2)? If so, whats the best way to obtain a file descriptor with which to wait on?

TIA, rotis23

rotis23
10-20-2003, 09:45 AM
some code maybe:

#include <sys/stat.h>
#include <signal.h>

void timed_out(){}

int main()
{
int timeout = 5,check_in = 0;
int *ch_res = NULL;
struct sigaction action;

bzero(&action, sizeof(action));
action.sa_handler = timed_out;
action.sa_flags = 0;
sigaction(SIGALRM, &action, 0);

char *h = "/tmp/test/dir/";

alarm(timeout);
ch_res = (int*)malloc(sizeof(int) * 1);
printf("set timeout; attempting to chdir to %s\n",h);
//try and chdir to broken nfs directory
ch_res[0] = chdir(h);
if(ch_res)printf("got result from chdir - %d\n",ch_res[0]);
alarm(0);

if(!ch_res)
{
printf("timeout whilst changing to directory %s - NFS problem?\n",h);
free(ch_res);
exit(1);
}

if (ch_res[0] < 0)
{
printf("Creating directory %s\n",h);

if(mkdir(h, 0755))
{
printf("Error making directory %s\n",h);
exit(1);
}
else
{
printf("Made directory %s\n",h);
}

//try again
if (chdir(h) < 0)
{
printf("Error changing to directory %s\n",h);
exit(1);
}
}
free(ch_res);

exit(0);
}

rotis23
10-20-2003, 01:13 PM
OK, I've found out some more info.

According to the man page for mount_nfs I am already passing the intr flag to allow keyboard interrupts; specifically SIGQUIT and SIGINT.

So, all I need to do is fork, wait and send my process a SIGINT signal.

Do others agree?

rotis23
10-20-2003, 03:02 PM
This is the answer - it can use a timeout on hard mounted nfs mounted directories.

It uses fork(2), pipe(2), child(2) and kill(2) to create a child that attempts to use the mount.

The parent uses select to set a timeout and listen to a pipe for a successful child response.

Remember to use the intr flag when mounting nfs shares!

#include <sys/stat.h>
#include <signal.h>
#include <stdio.h>
#include <time.h>


void timed_out(){}

int main()
{
int timeout = 5,check_in = 0;
int ch_res;
struct sigaction action;
FILE *temp_file = NULL;
int fd,rc,error;
int fds[2];
fd_set fdset;
struct timeval t;
pid_t child;

char *h = "/var/tmp/nfs/mount/somewhere/";

if(pipe(fds) != 0)
{
return NULL;
}
child = fork();
if(child == -1)
{
printf("Error forking child\n");
exit(1);
}

if( child == 0 )
{
char *buf = "ok";
printf("Child attempting to chdir\n");
chdir(h);
printf("Child writing to pipe\n");
write(fds[1],buf,3);
close(fds[0]);
close(fds[1]);
printf("Child exiting normally\n");
exit(0);
}
else
{
t.tv_sec = timeout;
t.tv_usec = 0;
FD_ZERO(&fdset);
FD_SET(fds[0], &fdset);

rc = select(fds[0] + 1,&fdset,NULL,NULL,&t);

if(rc == -1)
{
printf("Error in select\n");
close(fds[0]);
close(fds[1]);
exit(1);
}
else if(rc == 0)
{
printf("Timeout - possible nfs error\n");
kill(child,SIGINT);
close(fds[0]);
close(fds[1]);
exit(1);
}
else if(FD_ISSET(fds[0],&fdset))
{
printf("Got a response, nfs ok\n");
//close all stuff
close(fds[0]);
close(fds[1]);
}
}

ch_res = chdir(h);

if (ch_res < 0)
{
printf("Creating directory %s\n",h);

if(mkdir(h, 0755))
{
printf("Error making directory %s\n",h);
exit(1);
}
else
{
printf("Made directory %s\n",h);
}

if (chdir(h) < 0)
{
printf("Error changing to directory %s\n",h);
exit(1);
}
}
else
{
printf("Changed directory successfully %d\n",ch_res);
}

exit(0);
}