From d33ff301454fa1db9919674dbc2a37309bbd529f Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Thu, 30 Jan 2003 05:22:52 +0000 Subject: Portability fix for glob.h building in FreeBSD ports system. Implement a fix for bug # 2169: too many OSs, even major OSs like Solaris, don't properly implement SA_RESTART: important system calls like stat() can still fail when SA_RESTART is set. So, forget the BROKEN_RESTART config check and get rid of atomic_stat() and atomic_readdir(), and implement permanent wrappers for EINTR checking on various system calls (stat(), fstat(), opendir(), and readdir() so far). --- ChangeLog | 31 +++++++++++++++++++++++++++++++ arscan.c | 3 ++- commands.c | 4 +++- configure.in | 15 --------------- dir.c | 15 +++++++++++---- glob/ChangeLog | 6 ++++++ glob/glob.h | 12 ++++++++---- make.h | 27 ++++++++------------------- misc.c | 32 -------------------------------- read.c | 14 ++++++++++---- remake.c | 8 ++++++-- vpath.c | 46 ++++++++++++++++++++++++++-------------------- 12 files changed, 111 insertions(+), 102 deletions(-) diff --git a/ChangeLog b/ChangeLog index ef5bd87..903a64f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +2003-01-29 Paul D. Smith + + Fix bug # 2169, also reported by other people on various systems. + + * make.h: Some systems, such as Solaris and PTX, do not fully + implement POSIX-compliant SA_RESTART functionality; important + system calls like stat() and readdir() can still fail with EINTR + even if SA_RESTART has been set on the signal handler. So, + introduce macros EINTRLOOP() and ENULLLOOP() which can loop on + EINTR for system calls which return -1 or 0 (NULL), respectively, + on error. + Also, remove the old atomic_stat()/atomic_readdir() and + HAVE_BROKEN_RESTART handling. + + * configure.in: Remove setting of HAVE_BROKEN_RESTART. + + * arscan.c (ar_member_touch): Use EINTRLOOP() to wrap fstat(). + * remake.c (touch_file): Ditto. + + * commands.c (delete_target): Use EINTRLOOP() to wrap stat(). + * read.c (construct_include_path): Ditto. + * remake.c (name_mtime): Ditto. + * vpath.c (selective_vpath_search): Ditto. + * dir.c (find_directory): Ditto. + (local_stat): Ditto. + (find_directory): Use ENULLLOOP() to wrap opendir(). + (dir_contents_file_exists_p): Use ENULLLOOP() to wrap readdir(). + + * misc.c: Remove HAVE_BROKEN_RESTART, atomic_stat(), and + atomic_readdir() handling. + 2003-01-22 Paul D. Smith * function.c (func_call): Fix Bug #1744. If we're inside a diff --git a/arscan.c b/arscan.c index 2c67947..b1e9971 100644 --- a/arscan.c +++ b/arscan.c @@ -781,7 +781,8 @@ ar_member_touch (char *arname, char *memname) if (AR_HDR_SIZE != write (fd, (char *) &ar_hdr, AR_HDR_SIZE)) goto lose; /* The file's mtime is the time we we want. */ - if (fstat (fd, &statbuf) < 0) + EINTRLOOP (i, fstat (fd, &statbuf)); + if (i < 0) goto lose; #if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32) /* Advance member's time to that time */ diff --git a/commands.c b/commands.c index 30787a4..a6964d5 100644 --- a/commands.c +++ b/commands.c @@ -492,6 +492,7 @@ static void delete_target (struct file *file, char *on_behalf_of) { struct stat st; + int e; if (file->precious || file->phony) return; @@ -515,7 +516,8 @@ delete_target (struct file *file, char *on_behalf_of) } #endif - if (stat (file->name, &st) == 0 + EINTRLOOP (e, stat (file->name, &st)); + if (e == 0 && S_ISREG (st.st_mode) && FILE_TIMESTAMP_STAT_MODTIME (file->name, st) != file->last_mtime) { diff --git a/configure.in b/configure.in index 8df2e27..befba08 100644 --- a/configure.in +++ b/configure.in @@ -294,21 +294,6 @@ make_cv_sys_gnu_glob=no])]) # Tell automake about this, so it can build the right .c files. AM_CONDITIONAL(USE_LOCAL_GLOB, test "$make_cv_sys_gnu_glob" = no) -# PTX systems have a broken implementation of SA_RESTART. I know of -# no way to test for this behavior, so I'll just test for PTX - -case "$host" in - i386-sequent-sysv4) - AC_DEFINE(HAVE_BROKEN_RESTART, 1, [This system has SA_RESTART, but it doesn't work properly.]) - echo "" - echo "WARNING: The SA_RESTART sigaction() flag does not work on PTX." - echo " This causes 'make -j' to fail at random times." - echo " I am installing a workaround, which is mostly but not 100%" - echo " effective. If you see random failures during 'make -j'" - echo " you should either contact the bug list, or not use -j." - echo "" ;; -esac - # Let the makefile know what our build host is AC_DEFINE_UNQUOTED(MAKE_HOST,"$host",[Build host information.]) diff --git a/dir.c b/dir.c index 39f3e2a..7db0697 100644 --- a/dir.c +++ b/dir.c @@ -455,7 +455,7 @@ find_directory (char *name) #ifdef VMS r = vmsstat_dir (name, &st); #else - r = stat (name, &st); + EINTRLOOP (r, stat (name, &st)); #endif #ifdef WINDOWS32 @@ -536,7 +536,7 @@ find_directory (char *name) # endif #endif /* WINDOWS32 */ hash_insert_at (&directory_contents, dc, dc_slot); - dc->dirstream = opendir (name); + ENULLLOOP (dc->dirstream, opendir (name)); if (dc->dirstream == 0) /* Couldn't open the directory. Mark this by setting the `files' member to a nil pointer. */ @@ -645,13 +645,17 @@ dir_contents_file_exists_p (struct directory_contents *dir, char *filename) return 0; } - while ((d = readdir (dir->dirstream)) != 0) + while (1) { /* Enter the file in the hash table. */ unsigned int len; struct dirfile dirfile_key; struct dirfile **dirfile_slot; + ENULLLOOP (d, readdir (dir->dirstream)); + if (d == 0) + break; + #if defined(VMS) && defined(HAVE_DIRENT_H) /* In VMS we get file versions too, which have to be stripped off */ { @@ -1155,7 +1159,10 @@ extern int stat PARAMS ((const char *path, struct stat *sbuf)); static int local_stat (const char *path, struct stat *buf) { - return stat (path, buf); + int e; + + EINTRLOOP (e, stat (path, buf)); + return e; } #endif diff --git a/glob/ChangeLog b/glob/ChangeLog index 1ebf879..75c6888 100644 --- a/glob/ChangeLog +++ b/glob/ChangeLog @@ -1,3 +1,9 @@ +2003-01-30 Paul D. Smith + + * glob.h: Patch for FreeBSD by Mike Barcroft + Reported by Gerald Pfeifer . On + FreeBSD, declare __size_t to simply size_t. + 2002-04-22 Paul D. Smith * Makefile.am: Use automake 1.6. diff --git a/glob/glob.h b/glob/glob.h index 9f735fe..ca523f7 100644 --- a/glob/glob.h +++ b/glob/glob.h @@ -47,9 +47,12 @@ extern "C" { /* We need `size_t' for the following definitions. */ #ifndef __size_t -# if defined __GNUC__ && __GNUC__ >= 2 -typedef __SIZE_TYPE__ __size_t; +# if defined __FreeBSD__ +# define __size_t size_t # else +# if defined __GNUC__ && __GNUC__ >= 2 +typedef __SIZE_TYPE__ __size_t; +# else /* This is a guess. */ /*hb * Conflicts with DECCs aready defined type __size_t. @@ -57,9 +60,10 @@ typedef __SIZE_TYPE__ __size_t; * Anyway if DECC is used and __SIZE_T is defined then __size_t is * already defined (and I hope it's exactly the one we need here). */ -#if !(defined __DECC && defined __SIZE_T) +# if !(defined __DECC && defined __SIZE_T) typedef unsigned long int __size_t; -#endif +# endif +# endif # endif #else /* The GNU CC stddef.h version defines __size_t as empty. We need a real diff --git a/make.h b/make.h index 6648ea0..3ac47d1 100644 --- a/make.h +++ b/make.h @@ -539,24 +539,13 @@ extern int handling_fatal_signal; #endif -/* If we have broken SA_RESTART support, then wrap stat() and readdir() with - versions that handle EINTR. Note that there are still plenty of system - calls that can fail with EINTR but this, reportedly, gets the vast - majority of failure cases. If you still experience failures you'll need - to either get a system where SA_RESTART works, or you need to avoid -j. */ +/* Some systems (like Solaris, PTX, etc.) do not support the SA_RESTART flag + properly according to POSIX. So, we try to wrap common system calls with + checks for EINTR. Note that there are still plenty of system calls that + can fail with EINTR but this, reportedly, gets the vast majority of + failure cases. If you still experience failures you'll need to either get + a system where SA_RESTART works, or you need to avoid -j. */ -#ifdef HAVE_BROKEN_RESTART +#define EINTRLOOP(_v,_c) while (((_v)=_c)==-1 && errno==EINTR) -/* Here we make an assumption that a system with a broken SA_RESTART has - dirent.h. Right now the only system I know of in this category is PTX, and - it does have dirent.h. -*/ -#include - -#define stat(_f,_b) atomic_stat ((_f), (_b)) -#define readdir(_d) atomic_readdir (_d) - -extern int atomic_stat PARAMS ((const char *file, struct stat *buf)); -extern struct dirent *atomic_readdir PARAMS ((DIR *dir)); - -#endif +#define ENULLLOOP(_v,_c) while (((_v)=_c)==0 && errno==EINTR) diff --git a/misc.c b/misc.c index 5305220..ef754e5 100644 --- a/misc.c +++ b/misc.c @@ -828,35 +828,3 @@ get_path_max (void) return value; } #endif - - -#ifdef HAVE_BROKEN_RESTART - -#undef stat -#undef readdir - -int -atomic_stat (const char *file, struct stat *buf) -{ - int r; - - while ((r = stat (file, buf)) < 0) - if (errno != EINTR) - break; - - return r; -} - -struct dirent * -atomic_readdir (DIR *dir) -{ - struct dirent *r; - - while ((r = readdir (dir)) == NULL) - if (errno != EINTR) - break; - - return r; -} - -#endif /* HAVE_BROKEN_RESTART */ diff --git a/read.c b/read.c index 3e01572..a0bf5ca 100644 --- a/read.c +++ b/read.c @@ -2819,6 +2819,7 @@ construct_include_path (char **arg_dirs) while (*arg_dirs != 0) { char *dir = *arg_dirs++; + int e; if (dir[0] == '~') { @@ -2827,7 +2828,8 @@ construct_include_path (char **arg_dirs) dir = expanded; } - if (stat (dir, &stbuf) == 0 && S_ISDIR (stbuf.st_mode)) + EINTRLOOP (e, stat (dir, &stbuf)); + if (e == 0 && S_ISDIR (stbuf.st_mode)) { if (idx == max - 1) { @@ -2860,9 +2862,13 @@ construct_include_path (char **arg_dirs) #endif for (i = 0; default_include_directories[i] != 0; ++i) - if (stat (default_include_directories[i], &stbuf) == 0 - && S_ISDIR (stbuf.st_mode)) - dirs[idx++] = default_include_directories[i]; + { + int e; + + EINTRLOOP (e, stat (default_include_directories[i], &stbuf)); + if (e == 0 && S_ISDIR (stbuf.st_mode)) + dirs[idx++] = default_include_directories[i]; + } dirs[idx] = 0; diff --git a/remake.c b/remake.c index db1dd2c..c679d11 100644 --- a/remake.c +++ b/remake.c @@ -961,8 +961,10 @@ touch_file (struct file *file) { struct stat statbuf; char buf; + int e; - if (fstat (fd, &statbuf) < 0) + EINTRLOOP (e, fstat (fd, &statbuf)); + if (e < 0) TOUCH_ERROR ("touch: fstat: "); /* Rewrite character 0 same as it already is. */ if (read (fd, &buf, 1) < 0) @@ -1257,8 +1259,10 @@ static FILE_TIMESTAMP name_mtime (char *name) { struct stat st; + int e; - if (stat (name, &st) != 0) + EINTRLOOP (e, stat (name, &st)); + if (e != 0) { if (errno != ENOENT && errno != ENOTDIR) perror_with_name ("stat:", name); diff --git a/vpath.c b/vpath.c index 18aaaa9..5e04d08 100644 --- a/vpath.c +++ b/vpath.c @@ -507,27 +507,33 @@ selective_vpath_search (struct vpath *path, char **file, *n = '/'; #endif - if (!exists_in_cache /* Makefile-mentioned file need not exist. */ - || stat (name, &st) == 0) /* Does it really exist? */ + if (exists_in_cache) /* Makefile-mentioned file need not exist. */ { - /* We have found a file. - Store the name we found into *FILE for the caller. */ - - *file = savestring (name, (n + 1 - name) + flen); - - if (mtime_ptr != 0) - /* Store the modtime into *MTIME_PTR for the caller. - If we have had no need to stat the file here, - we record UNKNOWN_MTIME to indicate this. */ - *mtime_ptr = (exists_in_cache - ? FILE_TIMESTAMP_STAT_MODTIME (name, st) - : UNKNOWN_MTIME); - - free (name); - return 1; - } - else - exists = 0; + int e; + + EINTRLOOP (e, stat (name, &st)); /* Does it really exist? */ + if (e != 0) + { + exists = 0; + continue; + } + } + + /* We have found a file. + Store the name we found into *FILE for the caller. */ + + *file = savestring (name, (n + 1 - name) + flen); + + if (mtime_ptr != 0) + /* Store the modtime into *MTIME_PTR for the caller. + If we have had no need to stat the file here, + we record UNKNOWN_MTIME to indicate this. */ + *mtime_ptr = (exists_in_cache + ? FILE_TIMESTAMP_STAT_MODTIME (name, st) + : UNKNOWN_MTIME); + + free (name); + return 1; } } -- cgit v1.2.3