Date: Fri, 25 Apr 1997 15:29:11 +0300 (EEST) From: tri@iki.fi To: FreeBSD-gnats-submit@freebsd.org Cc: tri-bcc@pooh.tky.hut.fi Subject: kern/3384: Bug in telldir-closedir-opendir-seekdir Message-ID: <199704251229.PAA01865@pooh.tky.hut.fi> Resent-Message-ID: <199704251230.FAA11730@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 3384
>Category: kern
>Synopsis: telldir-seekdir can cause livelock
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Fri Apr 25 05:30:00 PDT 1997
>Last-Modified:
>Originator: Timo J. Rinne
>Organization:
Helsinki University of Technology
>Release: FreeBSD 3.0-CURRENT i386
>Environment:
i386 - Pentium 3.0-current 970209 - 9704??
>Description:
When traversing through directory structure like this pseudocode:
traverse(d) {
opendir(d)
while(e = readdir(d))
if (directory-p(e))
x = telldir(d)
closedir(d)
traverse(e)
opendir(d)
seekdir(d, x)
closedir(d)
}
Restoring of the current directory after subtreetraversal
causes the directory read to start from beginning leading
to livelock.
>How-To-Repeat:
My colleague Jukka Partanen kindly provided a test program.
Gets stuck when ran in directory with ordinary files and subdirectories.
Works in NetBSD and Linux, gets stuck in FreeBSD.
>Fix:
Sorry. No time to debug. We use different OS in our
production system.
>Audit-Trail:
>Unformatted:
>>>>>>>>>>>>>>>>>> C U T H E R E >>>>>>>>>>>>>>>>>>
/*
*
* dirtest.c
*
* Author: Jukka Partanen <jukka.partanen@research.nokia.com>
*
* Copyright (c) 1997 Nokia Research Center
* All rights reserved
*
* Created : Thu Apr 24 14:53:03 1997 partanen
* Last modified: Fri Apr 25 09:47:13 1997 partanen
*
* $Id$
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <limits.h>
static int process_dir(int namelen);
static char file[PATH_MAX+1];
int main(int argc, char *argv[])
{
char *name = argc > 1 ? argv[1] : ".";
int namelen;
strcpy(file, name);
namelen = strlen(file);
if (namelen && file[namelen - 1] == '/')
namelen--;
return process_dir(namelen);
}
static int process_dir(int namelen)
{
long dirpos;
DIR *dirp;
struct dirent *dp;
struct stat statbuf;
dirp = opendir(file);
if (!dirp) {
perror(file);
return 1;
}
while ((dp = readdir(dirp)) != NULL) {
file[namelen] = '/';
strcpy(file + namelen + 1, dp->d_name);
if (stat(file, &statbuf) < 0) {
perror(file);
} else {
printf("%s\n", file);
if ((statbuf.st_mode & S_IFDIR) &&
strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) {
dirpos = telldir(dirp);
closedir(dirp);
process_dir(namelen + strlen(dp->d_name) + 1);
file[namelen] = '\0';
dirp = opendir(file);
if (!dirp) {
perror(file);
return 1;
}
seekdir(dirp, dirpos);
}
}
file[namelen] = '\0';
}
closedir(dirp);
return 0;
}
>>>>>>>>>>>>>>>>>> C U T H E R E >>>>>>>>>>>>>>>>>>
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199704251229.PAA01865>
