2.1.*: unexpected ENOENT from creat(2), possible race condition?

Steffen Zahn (zahn@berlin.snafu.de)
Fri, 20 Nov 1998 20:48:40 +0100


Hello,

I tried the appended program on Linux 2.1.129 on a dual-P2/233 system
with glibc-2.0.7pre6, the filesystem is ext2. Sometimes
a creat(2) system call gives an errno of ENOENT (No such file or directory),
the program will issue the line:
do_child:creat: No such file or directory

According to the manpage of creat(2) this can only happen, if

ENOENT A directory component in pathname does not exist
or is a dangling symbolic link.

but this does not apply here, the pathname is relative to the
current directory and no symlinks are involved.

The program runs 100 processes doing cycles of creat,write,close,unlink
in parallel, all use the same constant filename.

The question is if that is just a documentation problem or a race condition
between creat and unlink.

Best regards
Steffen

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>

#define CHILDMAX 100
pid_t pids[CHILDMAX];
int next_pid;
pid_t father;

void sigint (int sig)
{
int i;
if( getpid()!=father )
exit(1);
for(i=0;i<next_pid;i++)
{
kill(pids[i],SIGINT);
}
}

void do_child()
{
char fn[20];
char buf[BUFSIZ];
int fd;
strcpy(fn,"tmp.tmp");
for(;;)
{
errno=0;
if( (fd=creat(fn,0600))<0 )
perror("do_child:creat");
else
{
if( write(fd,buf,sizeof(buf))!=sizeof(buf) )
perror("do_child:write");
if( close(fd)<0 )
perror("do_child:close");
}
if( ( unlink(fn)<0 ) && ( errno!=ENOENT ) ) /* ignore ENOENT */
perror("do_child:unlink");
}
}

int main(int argc,char **argv)
{
int i;
pid_t child;
struct sigaction act;

next_pid=0;
father=getpid();
act.sa_handler=sigint;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
sigaction(SIGINT,&act,NULL);
for(i=0;i<CHILDMAX;i++)
{
if( (child=fork())<0)
perror("Cannot fork");
else if( child==0 ) /* child */
{
act.sa_handler=SIG_DFL;
sigaction(SIGINT,&act,NULL);
fprintf(stderr,"Child %d started\n",(int)getpid()); fflush(stderr);
do_child();
return 0;
} else { /* father */
pids[next_pid++]=child;
}
}
fprintf(stderr,"Waiting\n");fflush(stderr);
for(;;)
{
child=wait(NULL);
if( (child==-1)&&(errno==ECHILD) )
{
fprintf(stderr,"ECHILD, no more childs\n"); fflush(stderr);
break;
}
fprintf(stderr,"%d stopped\n",(int)child); fflush(stderr);
}
return 0;
}

-- 
home email:  user@domain where domain=berlin.snafu.de, user=zahn
Use of my address for unsolicited commercial advertising is forbidden.
      2^3021377 - 1     |     "Where do you want to crash today?"

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/