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>