|
View:
New views
3 Messages
—
Rating Filter:
Alert me
|
|
|
i386/121656: [libc] [PATCH] telldir issues>Number: 121656 >Category: i386 >Synopsis: [libc] [PATCH] telldir issues >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-i386 >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Mar 13 01:10:01 UTC 2008 >Closed-Date: >Last-Modified: >Originator: Gary Stanley >Release: 7.0-RELEASE >Organization: >Environment: >Description: >How-To-Repeat: Here's some of the regression test program that show the problem. If you compile seekdir-twice.c with a simple "#define DEBUG" you'll get more useful info. Busted telldir/seekdir machine (RELENG_7) first found: a pos returned by telldir: 1 second found: b third found: c should be == second: b pos given to seekdir: 1 pos returned by telldir: 2 should be == second: c should be == second: c Fixed seekdir/telldir with included patch: first found: a pos returned by telldir: 673198160 second found: b third found: c should be == second: b pos given to seekdir: 673198160 pos returned by telldir: 673198160 should be == second: b should be == second: b >Fix: Apply libc.diff to RELENG_7/RELENG_6 and rereun regression test tools. Everything appears to pass and I've been using these on a few machine for the past couple of months. Patch attached with submission follows: # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # . # ./telldir-memuse.c # ./libc.diff # ./seekdir-twice.c # echo c - . mkdir -p . > /dev/null 2>&1 echo x - ./telldir-memuse.c sed 's/^X//' >./telldir-memuse.c << 'END-of-./telldir-memuse.c' X#include <stdlib.h> X#include <unistd.h> X#include <dirent.h> X#include <err.h> X X Xint main(void) { X DIR *dp; X long loc; X void *memused; X int i; X int oktouse = 4096; X X dp = opendir("."); X if (dp == NULL) X err(EXIT_FAILURE, "Could not open current directory"); X loc = telldir(dp); X memused = sbrk(0); X closedir(dp); X X for (i=0; i<1000; i++) { X dp = opendir("."); X if (dp == NULL) X err(EXIT_FAILURE, "Could not open current directory"); X loc = telldir(dp); X closedir(dp); X X if (sbrk(0) - memused > oktouse) { X warnx("Used %d extra bytes for %d telldir calls", X (sbrk(0)-memused), i); X oktouse = sbrk(0) - memused; X } X } X if (oktouse > 4096) { X errx(EXIT_FAILURE, "Failure: leaked %d bytes", oktouse); X } else { X printf("OK: used %d bytes\n", sbrk(0)-memused); X } X return 0; X} END-of-./telldir-memuse.c echo x - ./libc.diff sed 's/^X//' >./libc.diff << 'END-of-./libc.diff' X--- include/dirent.h.old 2003-12-07 15:10:06.000000000 -0600 X+++ include/dirent.h 2008-03-12 19:31:09.000000000 -0500 X@@ -69,7 +69,7 @@ X char *dd_buf; /* data buffer */ X int dd_len; /* size of data buffer */ X long dd_seek; /* magic cookie returned by getdirentries */ X- long dd_rewind; /* magic cookie for rewinding */ X+ void *dd_internal; /* state for seekdir/telldir */ X int dd_flags; /* flags for readdir */ X void *dd_lock; /* hack to avoid including <pthread.h> */ X struct _telldir *dd_td; /* telldir position recording */ Xdiff -u -r -N lib/libc.old/gen/closedir.c lib/libc/gen/closedir.c X--- lib/libc.old/gen/closedir.c 2007-01-08 18:27:53.000000000 -0600 X+++ lib/libc/gen/closedir.c 2008-03-12 19:22:10.000000000 -0500 X@@ -43,24 +43,31 @@ X X #include "libc_private.h" X #include "telldir.h" X+#include "dirent_private.h" X X /* X * close a directory. X */ X int X-closedir(dirp) X- DIR *dirp; X+closedir(DIR *dirp) X { X int fd; X+ struct dirpos *poslist; X X if (__isthreaded) X _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock); X- _seekdir(dirp, dirp->dd_rewind); /* free seekdir storage */ X fd = dirp->dd_fd; X dirp->dd_fd = -1; X dirp->dd_loc = 0; X- free((void *)dirp->dd_buf); X- _reclaim_telldir(dirp); X+ free(dirp->dd_buf); X+ X+ /* free seekdir/telldir storage */ X+ for (poslist = dirp->dd_internal; poslist; ) { X+ struct dirpos *nextpos = poslist->dp_next; X+ free(poslist); X+ poslist = nextpos; X+ } X+ X if (__isthreaded) { X _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock); X _pthread_mutex_destroy((pthread_mutex_t *)&dirp->dd_lock); Xdiff -u -r -N lib/libc.old/gen/dirent_private.h lib/libc/gen/dirent_private.h X--- lib/libc.old/gen/dirent_private.h 1969-12-31 18:00:00.000000000 -0600 X+++ lib/libc/gen/dirent_private.h 2008-03-12 19:22:10.000000000 -0500 X@@ -0,0 +1,17 @@ X+/* $NetBSD: dirent_private.h,v 1.1 2006/05/17 20:36:50 christos Exp $ */ X+ X+/* X+ * One struct _dirpos is malloced to describe the current directory X+ * position each time telldir is called. It records the current magic X+ * cookie returned by getdirentries and the offset within the buffer X+ * associated with that return value. X+ */ X+struct dirpos { X+ struct dirpos *dp_next; /* next structure in list */ X+ off_t dp_seek; /* magic cookie returned by getdirentries */ X+ long dp_loc; /* offset of entry in buffer */ X+}; X+ X+struct _dirdesc; X+void _seekdir_unlocked(struct _dirdesc *, long); X+long _telldir_unlocked(struct _dirdesc *); Xdiff -u -r -N lib/libc.old/gen/opendir.c lib/libc/gen/opendir.c X--- lib/libc.old/gen/opendir.c 2007-01-08 18:27:54.000000000 -0600 X+++ lib/libc/gen/opendir.c 2008-03-12 19:22:10.000000000 -0500 X@@ -47,21 +47,20 @@ X #include "un-namespace.h" X X #include "telldir.h" X+#include "dirent_private.h" X+ X /* X * Open a directory. X */ X DIR * X-opendir(name) X- const char *name; X+opendir(const char *name) X { X X return (__opendir2(name, DTF_HIDEW|DTF_NODUP)); X } X X DIR * X-__opendir2(name, flags) X- const char *name; X- int flags; X+__opendir2(const char *name, int flags) X { X DIR *dirp; X int fd; X@@ -270,7 +269,8 @@ X /* X * Set up seek point for rewinddir. X */ X- dirp->dd_rewind = telldir(dirp); X+ dirp->dd_internal = NULL; X+ (void)telldir(dirp); X X return (dirp); X Xdiff -u -r -N lib/libc.old/gen/readdir.c lib/libc/gen/readdir.c X--- lib/libc.old/gen/readdir.c 2007-01-08 18:27:55.000000000 -0600 X+++ lib/libc/gen/readdir.c 2008-03-12 19:22:10.000000000 -0500 X@@ -43,6 +43,7 @@ X X #include "libc_private.h" X #include "telldir.h" X+#include "dirent_private.h" X X /* X * get next entry in a directory. Xdiff -u -r -N lib/libc.old/gen/rewinddir.c lib/libc/gen/rewinddir.c X--- lib/libc.old/gen/rewinddir.c 2007-01-08 18:27:55.000000000 -0600 X+++ lib/libc/gen/rewinddir.c 2008-03-12 19:22:10.000000000 -0500 X@@ -37,12 +37,16 @@ X #include <dirent.h> X X #include "telldir.h" X+#include "dirent_private.h" X X void X-rewinddir(dirp) X- DIR *dirp; X+rewinddir(DIR *dirp) X { X X- _seekdir(dirp, dirp->dd_rewind); X- dirp->dd_rewind = telldir(dirp); X+ struct dirpos *dp = dirp->dd_internal; X+ X+ while (dp->dp_next) X+ dp = dp->dp_next; X+ X+ _seekdir(dirp, (long)(intptr_t)dp); X } Xdiff -u -r -N lib/libc.old/gen/seekdir.c lib/libc/gen/seekdir.c X--- lib/libc.old/gen/seekdir.c 2007-01-08 18:27:55.000000000 -0600 X+++ lib/libc/gen/seekdir.c 2008-03-12 19:22:10.000000000 -0500 X@@ -41,15 +41,14 @@ X X #include "libc_private.h" X #include "telldir.h" X+#include "dirent_private.h" X X /* X * Seek to an entry in a directory. X * _seekdir is in telldir.c so that it can share opaque data structures. X */ X void X-seekdir(dirp, loc) X- DIR *dirp; X- long loc; X+seekdir(DIR *dirp, long loc) X { X if (__isthreaded) X _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock); Xdiff -u -r -N lib/libc.old/gen/telldir.c lib/libc/gen/telldir.c X--- lib/libc.old/gen/telldir.c 2007-01-08 18:27:55.000000000 -0600 X+++ lib/libc/gen/telldir.c 2008-03-12 19:22:56.000000000 -0500 X@@ -45,33 +45,30 @@ X #include "libc_private.h" X #include "telldir.h" X X-/* X- * The option SINGLEUSE may be defined to say that a telldir X- * cookie may be used only once before it is freed. This option X- * is used to avoid having memory usage grow without bound. X- */ X-#define SINGLEUSE X+#include "dirent_private.h" X X /* X * return a pointer into a directory X */ X long X-telldir(dirp) X- DIR *dirp; X+telldir(DIR *dirp) X { X- struct ddloc *lp; X+ struct dirpos *lp; X X- if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL) X+ for (lp = dirp->dd_internal; lp; lp = lp->dp_next) X+ if (lp->dp_seek == dirp->dd_seek && X+ lp->dp_loc == dirp->dd_loc) X+ return (intptr_t)lp; X+ if ((lp = malloc(sizeof(*lp))) == NULL) X return (-1); X- if (__isthreaded) X- _pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock); X- lp->loc_index = dirp->dd_td->td_loccnt++; X- lp->loc_seek = dirp->dd_seek; X- lp->loc_loc = dirp->dd_loc; X- LIST_INSERT_HEAD(&dirp->dd_td->td_locq, lp, loc_lqe); X- if (__isthreaded) X- _pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock); X- return (lp->loc_index); X+ X+ lp->dp_seek = dirp->dd_seek; X+ lp->dp_loc = dirp->dd_loc; X+ lp->dp_next = dirp->dd_internal; X+ dirp->dd_internal = lp; X+ X+ return (intptr_t)lp; X+ X } X X /* X@@ -79,51 +76,23 @@ X * Only values returned by "telldir" should be passed to seekdir. X */ X void X-_seekdir(dirp, loc) X- DIR *dirp; X- long loc; X+_seekdir(DIR *dirp, long loc) X { X- struct ddloc *lp; X- struct dirent *dp; X- X- LIST_FOREACH(lp, &dirp->dd_td->td_locq, loc_lqe) { X- if (lp->loc_index == loc) X+ struct dirpos *lp; X+ for (lp = dirp->dd_internal; lp; lp = lp->dp_next) X+ if ((intptr_t)lp == loc) X break; X- } X+ X if (lp == NULL) X return; X- if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek) X- goto found; X- (void) lseek(dirp->dd_fd, (off_t)lp->loc_seek, SEEK_SET); X- dirp->dd_seek = lp->loc_seek; X- dirp->dd_loc = 0; X- while (dirp->dd_loc < lp->loc_loc) { X- dp = _readdir_unlocked(dirp); X- if (dp == NULL) X- break; X- } X-found: X-#ifdef SINGLEUSE X- LIST_REMOVE(lp, loc_lqe); X- free((caddr_t)lp); X-#endif X-} X X-/* X- * Reclaim memory for telldir cookies which weren't used. X- */ X-void X-_reclaim_telldir(dirp) X- DIR *dirp; X-{ X- struct ddloc *lp; X- struct ddloc *templp; X+ if (lp->dp_loc == dirp->dd_loc && lp->dp_seek == dirp->dd_seek) X+ return; X X- lp = LIST_FIRST(&dirp->dd_td->td_locq); X- while (lp != NULL) { X- templp = lp; X- lp = LIST_NEXT(lp, loc_lqe); X- free(templp); X- } X- LIST_INIT(&dirp->dd_td->td_locq); X+ dirp->dd_seek = lseek(dirp->dd_fd, lp->dp_seek, SEEK_SET); X+ dirp->dd_loc = 0; X+ while (dirp->dd_loc < lp->dp_loc) X+ if (_readdir_unlocked(dirp) == NULL) X+ break; X+ X } Xdiff -u -r -N lib/libc.old/gen/telldir.h lib/libc/gen/telldir.h X--- lib/libc.old/gen/telldir.h 2001-01-24 06:59:24.000000000 -0600 X+++ lib/libc/gen/telldir.h 2008-03-12 19:22:10.000000000 -0500 X@@ -38,19 +38,6 @@ X #include <sys/queue.h> X X /* X- * One of these structures is malloced to describe the current directory X- * position each time telldir is called. It records the current magic X- * cookie returned by getdirentries and the offset within the buffer X- * associated with that return value. X- */ X-struct ddloc { X- LIST_ENTRY(ddloc) loc_lqe; /* entry in list */ X- long loc_index; /* key associated with structure */ X- long loc_seek; /* magic cookie returned by getdirentries */ X- long loc_loc; /* offset of entry in buffer */ X-}; X- X-/* X * One of these structures is malloced for each DIR to record telldir X * positions. X */ END-of-./libc.diff echo x - ./seekdir-twice.c sed 's/^X//' >./seekdir-twice.c << 'END-of-./seekdir-twice.c' X#include <stdio.h> X#include <string.h> X#include <dirent.h> X#include <sys/stat.h> X Xint main(void) { X DIR *dp; X X mkdir("t", 0755); X creat("t/a", 0600); X creat("t/b", 0600); X creat("t/c", 0600); X X if (dp = opendir("t")) { X char *wasname; X struct dirent *entry; X long here; X X /* skip two */ X entry = readdir(dp); X entry = readdir(dp); X entry = readdir(dp); X printf("first found: %s\n", entry->d_name); X X here = telldir(dp); X printf("pos returned by telldir: %d\n", here); X entry = readdir(dp); X printf("second found: %s\n", entry->d_name); X X wasname = strdup(entry->d_name); X entry = readdir(dp); X printf("third found: %s\n", entry->d_name); X X seekdir(dp, here); X entry = readdir(dp); X printf("should be == second: %s\n", entry->d_name); X X printf("pos given to seekdir: %d\n", here); X seekdir(dp, here); X here = telldir(dp); X printf("pos returned by telldir: %d\n", here); X X entry = readdir(dp); X printf("should be == second: %s\n", entry->d_name); X X seekdir(dp, here); X entry = readdir(dp); X printf("should be == second: %s\n", entry->d_name); X X closedir(dp); X } X return 0; X} END-of-./seekdir-twice.c exit >Release-Note: >Audit-Trail: >Unformatted: _______________________________________________ freebsd-i386@... mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-i386 To unsubscribe, send any mail to "freebsd-i386-unsubscribe@..." |
|
|
|
|
|
|
| Free embeddable forum powered by Nabble | Forum Help |