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).
This commit is contained in:
Paul Smith 2003-01-30 05:22:52 +00:00
parent d15a484098
commit d33ff30145
12 changed files with 108 additions and 99 deletions

View file

@ -1,3 +1,34 @@
2003-01-29 Paul D. Smith <psmith@gnu.org>
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 <psmith@gnu.org>
* function.c (func_call): Fix Bug #1744. If we're inside a

View file

@ -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 */

View file

@ -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)
{

View file

@ -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.])

15
dir.c
View file

@ -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

View file

@ -1,3 +1,9 @@
2003-01-30 Paul D. Smith <psmith@gnu.org>
* glob.h: Patch for FreeBSD by Mike Barcroft <mike@freebsd.org>
Reported by Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>. On
FreeBSD, declare __size_t to simply size_t.
2002-04-22 Paul D. Smith <psmith@gnu.org>
* Makefile.am: Use automake 1.6.

View file

@ -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

27
make.h
View file

@ -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 <dirent.h>
#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)

32
misc.c
View file

@ -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 */

14
read.c
View file

@ -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;

View file

@ -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);

40
vpath.c
View file

@ -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. */
int e;
*file = savestring (name, (n + 1 - name) + flen);
EINTRLOOP (e, stat (name, &st)); /* Does it really exist? */
if (e != 0)
{
exists = 0;
continue;
}
}
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);
/* We have found a file.
Store the name we found into *FILE for the caller. */
free (name);
return 1;
}
else
exists = 0;
*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;
}
}