From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9756 invoked by alias); 4 Nov 2003 19:42:53 -0000 Mailing-List: contact libc-hacker-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-hacker-owner@sources.redhat.com Received: (qmail 9737 invoked from network); 4 Nov 2003 19:42:53 -0000 Received: from unknown (HELO sunsite.ms.mff.cuni.cz) (195.113.19.66) by sources.redhat.com with SMTP; 4 Nov 2003 19:42:53 -0000 Received: from sunsite.ms.mff.cuni.cz (sunsite.mff.cuni.cz [127.0.0.1]) by sunsite.ms.mff.cuni.cz (8.12.8/8.12.8) with ESMTP id hA4Hcm2c004604; Tue, 4 Nov 2003 18:38:48 +0100 Received: (from jakub@localhost) by sunsite.ms.mff.cuni.cz (8.12.8/8.12.8/Submit) id hA4Hcltf004602; Tue, 4 Nov 2003 18:38:47 +0100 Date: Tue, 04 Nov 2003 19:42:00 -0000 From: Jakub Jelinek To: Ulrich Drepper , Roland McGrath Cc: Glibc hackers Subject: [PATCH] Fix ftw Message-ID: <20031104173847.GD12344@sunsite.ms.mff.cuni.cz> Reply-To: Jakub Jelinek Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4i X-SW-Source: 2003-11/txt/msg00002.txt.bz2 Hi! The following testcase shows ftw leaking filedescriptors (one per call) and the attached patch seems to fix it. 2003-11-04 Jakub Jelinek * io/ftw.c (ftw_dir): Close dir if callback with FTW_D type returns non-zero. * io/Makefile (tests): Add bug-ftw4. * io/bug-ftw4.c: New test. --- libc/io/Makefile.jj 2003-10-29 00:18:42.000000000 +0100 +++ libc/io/Makefile 2003-11-04 19:40:10.000000000 +0100 @@ -57,7 +57,7 @@ static-only-routines = stat fstat lstat others := pwd test-srcs := ftwtest tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \ - tst-fcntl bug-ftw1 bug-ftw2 bug-ftw3 tst-statvfs + tst-fcntl bug-ftw1 bug-ftw2 bug-ftw3 bug-ftw4 tst-statvfs distribute := ftwtest-sh --- libc/io/ftw.c.jj 2003-06-11 23:48:58.000000000 +0200 +++ libc/io/ftw.c 2003-11-04 19:57:42.000000000 +0100 @@ -476,23 +476,27 @@ ftw_dir (struct ftw_data *data, struct S { result = (*data->func) (data->dirbuf, st, FTW_D, &data->ftw); if (result != 0) - return result; - } - - /* If necessary, change to this directory. */ - if (data->flags & FTW_CHDIR) - { - if (__fchdir (dirfd (dir.stream)) < 0) { - int save_err = errno; + int save_err; +fail: + save_err = errno; __closedir (dir.stream); __set_errno (save_err); if (data->actdir-- == 0) data->actdir = data->maxdir - 1; data->dirstreams[data->actdir] = NULL; + return result; + } + } - return -1; + /* If necessary, change to this directory. */ + if (data->flags & FTW_CHDIR) + { + if (__fchdir (dirfd (dir.stream)) < 0) + { + result = -1; + goto fail; } } --- libc/io/bug-ftw4.c.jj 2003-11-04 19:39:53.000000000 +0100 +++ libc/io/bug-ftw4.c 2003-11-04 19:43:57.000000000 +0100 @@ -0,0 +1,124 @@ +/* Test if ftw function doesn't leak fds. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +static int cb_called; + +static int +cb (const char *name, const struct stat64 *st, int type) +{ + return cb_called++ & 1; +} + +int +main (void) +{ + char name[32] = "/tmp/ftwXXXXXX", *p; + int ret, i, result = 0, fd, fd1, fd2; + + if (mkdtemp (name) == NULL) + { + printf ("Couldn't make temporary directory: %m\n"); + exit (EXIT_FAILURE); + } + p = strchr (name, '\0'); + strcpy (p, "/1"); + if (mkdir (name, 0755) < 0) + { + printf ("Couldn't make temporary subdirectory: %m\n"); + exit (EXIT_FAILURE); + } + *p = '\0'; + + ret = ftw64 (name, cb, 20); + if (ret != 1) + { + printf ("ftw64 returned %d instead of 1", ret); + result = 1; + } + + fd = open (name, O_RDONLY); + if (fd < 0) + { + printf ("open failed: %m\n"); + result = 1; + } + fd1 = open (name, O_RDONLY); + if (fd1 < 0) + { + printf ("open failed: %m\n"); + result = 1; + } + else + close (fd1); + if (fd >= 0) + close (fd); + + for (i = 0; i < 128; ++i) + { + ret = ftw64 (name, cb, 20); + if (ret != 1) + { + printf ("ftw64 returned %d instead of 1", ret); + result = 1; + } + } + + fd = open (name, O_RDONLY); + if (fd < 0) + { + printf ("open failed: %m\n"); + result = 1; + } + fd2 = open (name, O_RDONLY); + if (fd2 < 0) + { + printf ("open failed: %m\n"); + result = 1; + } + else + close (fd2); + if (fd >= 0) + close (fd); + + if (fd2 >= fd1 + 128) + { + printf ("ftw64 leaking fds: %d -> %d\n", fd1, fd2); + result = 1; + } + + if (cb_called != 129 * 2) + { + printf ("callback called %d times\n", cb_called); + result = 1; + } + + strcpy (p, "/1"); + rmdir (name); + *p = '\0'; + rmdir (name); + return result; +} Jakub