From: Paul Eggert <eggert@cs.ucla.edu>
To: 13944@debbugs.gnu.org
Subject: bug#13944: file synchronization fixes
Date: Wed, 13 Mar 2013 00:38:00 -0700 [thread overview]
Message-ID: <51402CD8.1050005@cs.ucla.edu> (raw)
[-- Attachment #1: Type: text/plain, Size: 1246 bytes --]
Tags: patch
The new code for creating regular-file lock files has a problem if
the system crashes while the lock file is being created: due to
races inside the file system, if the crash occurs at the wrong time
the file system may end up with an empty regular-file lock file,
which after the reboot will cause Emacs to bypass locking for that
file indefinitely (unless the empty lock file is removed manually
by the user).
On a POSIX-conforming system the problem can occur only if the
system crashes just as a lock file is being created. Fixing this
requires using a synchronization primitive such as fsync on the
newly created file, before renaming it.
While looking into this I noticed some other file synchronization
problems. fsync is used sometimes when fdatasync will do. Emacs
does not consistently retry fsync after being interrupted. It
sometimes incorrectly reports an error merely because fsync isn't
supported. And it sometimes incorrectly skips fsync merely because
we are on a non-BSD system.
Attached a patch which I'd like to install. If MS-Windows has fdatasync
already this should build on MS-Windows; if not, the MS-Windows port
needs to compile lib/fdatasync.c or support an fdatasync substitute
in some other way.
[-- Attachment #2: fsync.txt --]
[-- Type: text/plain, Size: 23331 bytes --]
=== modified file 'ChangeLog'
--- ChangeLog 2013-03-13 07:15:17 +0000
+++ ChangeLog 2013-03-13 07:31:15 +0000
@@ -1,5 +1,12 @@
2013-03-13 Paul Eggert <eggert@cs.ucla.edu>
+ File synchronization fixes.
+ * configure.ac (BSD_SYSTEM, BSD_SYSTEM_AHB): Remove; no longer needed.
+ (fsync): Remove check; now done by gnulib.
+ * lib/fdatasync.c, lib/fsync.c, m4/fdatasync.m4, m4/fsync.m4:
+ New files, from gnulib.
+ * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
+
Merge from gnulib, incorporating:
2013-03-13 putenv: port to Solaris 10
2013-03-12 mktime: fix configure typo
=== modified file 'admin/CPP-DEFINES'
--- admin/CPP-DEFINES 2013-02-25 05:55:37 +0000
+++ admin/CPP-DEFINES 2013-03-13 05:52:50 +0000
@@ -9,7 +9,6 @@
AIX
_AIX
-BSD_SYSTEM
CYGWIN Compiling the Cygwin port.
__CYGWIN__ Ditto
GNU_LINUX
@@ -149,7 +148,6 @@
HAVE_FREEIFADDRS
HAVE_FREETYPE
HAVE_FSEEKO
-HAVE_FSYNC
HAVE_FUTIMENS
HAVE_FUTIMES
HAVE_FUTIMESAT
=== modified file 'admin/ChangeLog'
--- admin/ChangeLog 2013-03-11 22:32:07 +0000
+++ admin/ChangeLog 2013-03-13 05:52:50 +0000
@@ -1,3 +1,9 @@
+2013-03-13 Paul Eggert <eggert@cs.ucla.edu>
+
+ File synchronization fixes.
+ * CPP-DEFINES (BSD_SYSTEM, HAVE_FSYNC): Remove.
+ * merge-gnulib (GNULIB_MODULES): Add fsync, fdatasync.
+
2013-03-11 Paul Eggert <eggert@cs.ucla.edu>
* notes/unicode: Improve notes about Emacs source file encoding.
=== modified file 'admin/merge-gnulib'
--- admin/merge-gnulib 2013-02-11 23:37:18 +0000
+++ admin/merge-gnulib 2013-03-13 05:23:47 +0000
@@ -29,7 +29,8 @@
alloca-opt c-ctype c-strcase
careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512
dtoastr dtotimespec dup2 environ execinfo faccessat
- fcntl-h fdopendir filemode fstatat getloadavg getopt-gnu gettime gettimeofday
+ fcntl-h fdatasync fdopendir filemode fstatat fsync
+ getloadavg getopt-gnu gettime gettimeofday
ignore-value intprops largefile lstat
manywarnings memrchr mktime
pselect pthread_sigmask putenv readlink readlinkat
=== modified file 'configure.ac'
--- configure.ac 2013-03-06 08:01:47 +0000
+++ configure.ac 2013-03-13 05:52:50 +0000
@@ -2872,7 +2872,7 @@
utimes getrlimit setrlimit shutdown getaddrinfo \
strsignal setitimer \
sendto recvfrom getsockname getpeername getifaddrs freeifaddrs \
-gai_strerror mkstemp getline getdelim fsync sync \
+gai_strerror mkstemp getline getdelim sync \
difftime posix_memalign \
getpwent endpwent getgrent endgrent \
touchlock \
@@ -3774,7 +3774,6 @@
dnl Define symbols to identify the version of Unix this is.
dnl Define all the symbols that apply correctly.
-AH_TEMPLATE(BSD_SYSTEM, [Define if the system is compatible with BSD 4.2.])
AH_TEMPLATE(DOS_NT, [Define if the system is MS DOS or MS Windows.])
AH_TEMPLATE(MSDOS, [Define if the system is MS DOS.])
AH_TEMPLATE(USG, [Define if the system is compatible with System III.])
@@ -3798,30 +3797,12 @@
;;
darwin)
- dnl BSD4_3 and BSD4_4 are already defined in sys/param.h.
- AC_DEFINE(BSD_SYSTEM, [])
- dnl More specific than the above two. We cannot use __APPLE__ as this
- dnl may not be defined on non-OSX Darwin, and we cannot define DARWIN
- dnl here because Panther and lower CoreFoundation.h uses DARWIN to
+ dnl Not __APPLE__, as this may not be defined on non-OSX Darwin.
+ dnl Not DARWIN, because Panther and lower CoreFoundation.h use DARWIN to
dnl distinguish OS X from pure Darwin.
AC_DEFINE(DARWIN_OS, [], [Define if the system is Darwin.])
;;
- freebsd)
- dnl Hack to avoid calling AC_PREPROC_IFELSE multiple times.
- dnl Would not be needed with autoconf >= 2.67, where the
- dnl preprocessed output is accessible in "conftest.i".
- AC_DEFINE(BSD_SYSTEM_AHB, 1, [Define if AH_BOTTOM should change BSD_SYSTEM.])
- ;;
-
- gnu | netbsd | openbsd )
- AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[
-#ifndef BSD_SYSTEM
-# error "BSD_SYSTEM not defined"
-#endif
- ]], [[]])], [], AC_DEFINE(BSD_SYSTEM, 43) )
- ;;
-
gnu-linux | gnu-kfreebsd )
AC_DEFINE(USG, [])
AC_DEFINE(GNU_LINUX, [], [Define if ths system is compatible with GNU/Linux.])
@@ -4185,15 +4166,8 @@
LD_SWITCH_SYSTEM_TEMACS="-fno-pie -prebind $libs_nsgui -Xlinker -headerpad -Xlinker $headerpad_extra"
## This is here because src/Makefile.in did some extra fiddling around
- ## with LD_SWITCH_SYSTEM. The cpp logic was:
- ## #ifndef LD_SWITCH_SYSTEM
- ## #if !defined (__GNUC__) && ((defined (BSD_SYSTEM) && !defined (COFF)))
- ## Since all the *bsds define LD_SWITCH_SYSTEM, this simplifies to:
- ## not using gcc, darwin.
- ## Because this was done in src/Makefile.in, the resulting part of
- ## LD_SWITCH_SYSTEM was not used in configure (ie, in ac_link).
- ## It therefore seems cleaner to put this in LD_SWITCH_SYSTEM_TEMACS,
- ## rather than LD_SWITCH_SYSTEM.
+ ## with LD_SWITCH_SYSTEM. It seems cleaner to put this in
+ ## LD_SWITCH_SYSTEM_TEMACS instead,
test "x$LD_SWITCH_SYSTEM" = "x" && test "x$GCC" != "xyes" && \
LD_SWITCH_SYSTEM_TEMACS="-X $LD_SWITCH_SYSTEM_TEMACS"
;;
=== modified file 'lib-src/ChangeLog'
--- lib-src/ChangeLog 2013-03-13 07:27:34 +0000
+++ lib-src/ChangeLog 2013-03-13 07:31:15 +0000
@@ -1,5 +1,14 @@
2013-03-13 Paul Eggert <eggert@cs.ucla.edu>
+ File synchronization fixes.
+ * Makefile.in (LIB_FDATASYNC): New macro.
+ (emacsclient${EXEEXT}): Use it.
+ * emacsclient.c (main): Use fdatasync, not fsync, since we don't
+ care about metadata. Keep trying if interrupted.
+ * movemail.c (main, popmail): Don't worry about BSD_SYSTEM, since
+ fsync is available everywhere (or there is a substitute). Don't
+ report an error if fsync returns EINVAL.
+
Static checking by Sun C 5.12.
* etags.c (analyse_regex): Omit unreachable code.
=== modified file 'lib-src/Makefile.in'
--- lib-src/Makefile.in 2013-01-01 09:11:05 +0000
+++ lib-src/Makefile.in 2013-03-13 05:42:28 +0000
@@ -161,6 +161,8 @@
LIBS_MAIL=@LIBS_MAIL@
## empty or -lrt or -lposix4 if HAVE_CLOCK_GETTIME
LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@
+## empty or -lrt or -lposix4 if HAVE_FDATASYNC
+LIB_FDATASYNC = @LIB_FDATASYNC@
## Extra libraries to use when linking movemail.
LIBS_MOVE = $(LIBS_MAIL) $(KRB4LIB) $(DESLIB) $(KRB5LIB) $(CRYPTOLIB) \
@@ -334,7 +336,7 @@
emacsclient${EXEEXT}: ${srcdir}/emacsclient.c $(config_h)
$(CC) ${ALL_CFLAGS} ${srcdir}/emacsclient.c \
-DVERSION="\"${version}\"" \
- $(LOADLIBES) -o emacsclient
+ $(LOADLIBES) $(LIB_FDATASYNC) -o emacsclient
hexl${EXEEXT}: ${srcdir}/hexl.c $(config_h)
$(CC) ${ALL_CFLAGS} ${srcdir}/hexl.c $(LOADLIBES) -o hexl
=== modified file 'lib-src/emacsclient.c'
--- lib-src/emacsclient.c 2013-01-02 16:13:04 +0000
+++ lib-src/emacsclient.c 2013-03-13 05:23:47 +0000
@@ -1724,7 +1724,8 @@
needlf = 2;
}
fflush (stdout);
- fsync (1);
+ while (fdatasync (1) != 0 && errno == EINTR)
+ continue;
/* Now, wait for an answer and print any messages. */
while (exit_status == EXIT_SUCCESS)
@@ -1825,7 +1826,8 @@
if (needlf)
printf ("\n");
fflush (stdout);
- fsync (1);
+ while (fdatasync (1) != 0 && errno == EINTR)
+ continue;
if (rl < 0)
exit_status = EXIT_FAILURE;
=== modified file 'lib-src/movemail.c'
--- lib-src/movemail.c 2013-03-13 01:05:40 +0000
+++ lib-src/movemail.c 2013-03-13 05:23:47 +0000
@@ -466,10 +466,8 @@
}
}
-#ifdef BSD_SYSTEM
- if (fsync (outdesc) < 0)
+ if (fsync (outdesc) != 0 && errno != EINVAL)
pfatal_and_delete (outname);
-#endif
/* Prevent symlink attacks truncating other users' mailboxes */
if (setregid (-1, real_gid) < 0)
@@ -750,21 +748,14 @@
}
}
- /* On AFS, a call to write only modifies the file in the local
- * workstation's AFS cache. The changes are not written to the server
- * until a call to fsync or close is made. Users with AFS home
- * directories have lost mail when over quota because these checks were
- * not made in previous versions of movemail. */
-
-#ifdef BSD_SYSTEM
- if (fsync (mbfi) < 0)
+ if (fsync (mbfi) != 0 && errno != EINVAL)
{
error ("Error in fsync: %s", strerror (errno), 0);
+ close (mbfi);
return EXIT_FAILURE;
}
-#endif
- if (close (mbfi) == -1)
+ if (close (mbfi) != 0)
{
error ("Error in close: %s", strerror (errno), 0);
return EXIT_FAILURE;
=== added file 'lib/fdatasync.c'
--- lib/fdatasync.c 1970-01-01 00:00:00 +0000
+++ lib/fdatasync.c 2013-03-13 05:23:47 +0000
@@ -0,0 +1,27 @@
+/* Emulate fdatasync on platforms that lack it.
+
+ Copyright (C) 2011-2013 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <unistd.h>
+
+int
+fdatasync (int fd)
+{
+ /* This does more work than strictly necessary, but is the best we
+ can do portably. */
+ return fsync (fd);
+}
=== added file 'lib/fsync.c'
--- lib/fsync.c 1970-01-01 00:00:00 +0000
+++ lib/fsync.c 2013-03-13 05:23:47 +0000
@@ -0,0 +1,83 @@
+/* Emulate fsync on platforms that lack it, primarily Windows and
+ cross-compilers like MinGW.
+
+ This is derived from sqlite3 sources.
+ http://www.sqlite.org/cvstrac/rlog?f=sqlite/src/os_win.c
+ http://www.sqlite.org/copyright.html
+
+ Written by Richard W.M. Jones <rjones.at.redhat.com>
+
+ Copyright (C) 2008-2013 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <unistd.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+/* FlushFileBuffers */
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+
+# include <errno.h>
+
+/* Get _get_osfhandle. */
+# include "msvc-nothrow.h"
+
+int
+fsync (int fd)
+{
+ HANDLE h = (HANDLE) _get_osfhandle (fd);
+ DWORD err;
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (!FlushFileBuffers (h))
+ {
+ /* Translate some Windows errors into rough approximations of Unix
+ * errors. MSDN is useless as usual - in this case it doesn't
+ * document the full range of errors.
+ */
+ err = GetLastError ();
+ switch (err)
+ {
+ case ERROR_ACCESS_DENIED:
+ /* For a read-only handle, fsync should succeed, even though we have
+ no way to sync the access-time changes. */
+ return 0;
+
+ /* eg. Trying to fsync a tty. */
+ case ERROR_INVALID_HANDLE:
+ errno = EINVAL;
+ break;
+
+ default:
+ errno = EIO;
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
+#else /* !Windows */
+
+# error "This platform lacks fsync function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib."
+
+#endif /* !Windows */
=== modified file 'lib/gnulib.mk'
--- lib/gnulib.mk 2013-02-11 23:37:18 +0000
+++ lib/gnulib.mk 2013-03-13 05:23:47 +0000
@@ -21,7 +21,7 @@
# the same distribution terms as the rest of that program.
#
# Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=dup --avoid=errno --avoid=fchdir --avoid=fcntl --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl-h fdopendir filemode fstatat getloadavg getopt-gnu gettime gettimeofday ignore-value intprops largefile lstat manywarnings memrchr mktime pselect pthread_sigmask putenv readlink readlinkat sig2str socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timer-time timespec-add timespec-sub unsetenv utimens warnings
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=dup --avoid=errno --avoid=fchdir --avoid=fcntl --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday ignore-value intprops largefile lstat manywarnings memrchr mktime pselect pthread_sigmask putenv readlink readlinkat sig2str socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timer-time timespec-add timespec-sub unsetenv utimens warnings
MOSTLYCLEANFILES += core *.stackdump
@@ -297,6 +297,15 @@
## end gnulib module fcntl-h
+## begin gnulib module fdatasync
+
+
+EXTRA_DIST += fdatasync.c
+
+EXTRA_libgnu_a_SOURCES += fdatasync.c
+
+## end gnulib module fdatasync
+
## begin gnulib module fdopendir
@@ -332,6 +341,15 @@
## end gnulib module fstatat
+## begin gnulib module fsync
+
+
+EXTRA_DIST += fsync.c
+
+EXTRA_libgnu_a_SOURCES += fsync.c
+
+## end gnulib module fsync
+
## begin gnulib module getgroups
if gl_GNULIB_ENABLED_getgroups
=== added file 'm4/fdatasync.m4'
--- m4/fdatasync.m4 1970-01-01 00:00:00 +0000
+++ m4/fdatasync.m4 2013-03-13 05:23:47 +0000
@@ -0,0 +1,32 @@
+# fdatasync.m4 serial 4
+dnl Copyright (C) 2008-2013 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_FDATASYNC],
+[
+ AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+
+ dnl Using AC_CHECK_FUNCS_ONCE would break our subsequent AC_SEARCH_LIBS
+ AC_CHECK_DECLS_ONCE([fdatasync])
+ LIB_FDATASYNC=
+ AC_SUBST([LIB_FDATASYNC])
+
+ if test $ac_cv_have_decl_fdatasync = no; then
+ HAVE_DECL_FDATASYNC=0
+ dnl Mac OS X 10.7 has fdatasync but does not declare it.
+ AC_CHECK_FUNCS([fdatasync])
+ if test $ac_cv_func_fdatasync = no; then
+ HAVE_FDATASYNC=0
+ fi
+ else
+ dnl Solaris <= 2.6 has fdatasync() in libposix4.
+ dnl Solaris 7..10 has it in librt.
+ gl_saved_libs=$LIBS
+ AC_SEARCH_LIBS([fdatasync], [rt posix4],
+ [test "$ac_cv_search_fdatasync" = "none required" ||
+ LIB_FDATASYNC=$ac_cv_search_fdatasync])
+ LIBS=$gl_saved_libs
+ fi
+])
=== added file 'm4/fsync.m4'
--- m4/fsync.m4 1970-01-01 00:00:00 +0000
+++ m4/fsync.m4 2013-03-13 05:23:47 +0000
@@ -0,0 +1,17 @@
+# fsync.m4 serial 2
+dnl Copyright (C) 2008-2013 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_FSYNC],
+[
+ AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+ AC_CHECK_FUNCS_ONCE([fsync])
+ if test $ac_cv_func_fsync = no; then
+ HAVE_FSYNC=0
+ fi
+])
+
+# Prerequisites of lib/fsync.c.
+AC_DEFUN([gl_PREREQ_FSYNC], [:])
=== modified file 'm4/gnulib-comp.m4'
--- m4/gnulib-comp.m4 2013-03-01 15:16:43 +0000
+++ m4/gnulib-comp.m4 2013-03-13 05:23:47 +0000
@@ -63,10 +63,12 @@
# Code from module extern-inline:
# Code from module faccessat:
# Code from module fcntl-h:
+ # Code from module fdatasync:
# Code from module fdopendir:
# Code from module filemode:
# Code from module fpending:
# Code from module fstatat:
+ # Code from module fsync:
# Code from module getgroups:
# Code from module getloadavg:
# Code from module getopt-gnu:
@@ -187,6 +189,11 @@
gl_MODULE_INDICATOR([faccessat])
gl_UNISTD_MODULE_INDICATOR([faccessat])
gl_FCNTL_H
+ gl_FUNC_FDATASYNC
+ if test $HAVE_FDATASYNC = 0; then
+ AC_LIBOBJ([fdatasync])
+ fi
+ gl_UNISTD_MODULE_INDICATOR([fdatasync])
gl_FUNC_FDOPENDIR
if test $HAVE_FDOPENDIR = 0 || test $REPLACE_FDOPENDIR = 1; then
AC_LIBOBJ([fdopendir])
@@ -204,6 +211,12 @@
AC_LIBOBJ([fstatat])
fi
gl_SYS_STAT_MODULE_INDICATOR([fstatat])
+ gl_FUNC_FSYNC
+ if test $HAVE_FSYNC = 0; then
+ AC_LIBOBJ([fsync])
+ gl_PREREQ_FSYNC
+ fi
+ gl_UNISTD_MODULE_INDICATOR([fsync])
gl_GETLOADAVG
if test $HAVE_GETLOADAVG = 0; then
AC_LIBOBJ([getloadavg])
@@ -743,12 +756,14 @@
lib/execinfo.in.h
lib/faccessat.c
lib/fcntl.in.h
+ lib/fdatasync.c
lib/fdopendir.c
lib/filemode.c
lib/filemode.h
lib/fpending.c
lib/fpending.h
lib/fstatat.c
+ lib/fsync.c
lib/ftoastr.c
lib/ftoastr.h
lib/getgroups.c
@@ -842,10 +857,12 @@
m4/faccessat.m4
m4/fcntl-o.m4
m4/fcntl_h.m4
+ m4/fdatasync.m4
m4/fdopendir.m4
m4/filemode.m4
m4/fpending.m4
m4/fstatat.m4
+ m4/fsync.m4
m4/getgroups.m4
m4/getloadavg.m4
m4/getopt.m4
=== modified file 'src/ChangeLog'
--- src/ChangeLog 2013-03-13 07:27:34 +0000
+++ src/ChangeLog 2013-03-13 07:31:15 +0000
@@ -1,5 +1,14 @@
2013-03-13 Paul Eggert <eggert@cs.ucla.edu>
+ File synchronization fixes.
+ * Makefile.in (LIB_FDATASYNC): New macro.
+ (LIBES): Use it.
+ * conf_post.h (BSD_SYSTEM, BSD_SYSTEM_AHB): Remove; no longer needed.
+ * fileio.c (Fwrite_region, write_region_inhibit_fsync):
+ Don't worry about HAVE_FSYNC, since a substitute fsync is
+ available if the system lacks one.
+ (Fwrite_regin): Retry fsync if interrupted.
+
Static checking by Sun C 5.12.
* alloc.c (buffer_memory_full) [REL_ALLOC]:
* bytecode.c (exec_byte_code):
=== modified file 'src/Makefile.in'
--- src/Makefile.in 2013-02-25 05:55:37 +0000
+++ src/Makefile.in 2013-03-13 05:42:28 +0000
@@ -139,6 +139,7 @@
LIB_CLOCK_GETTIME=@LIB_CLOCK_GETTIME@
LIB_EACCESS=@LIB_EACCESS@
+LIB_FDATASYNC=@LIB_FDATASYNC@
LIB_TIMER_TIME=@LIB_TIMER_TIME@
DBUS_CFLAGS = @DBUS_CFLAGS@
@@ -391,7 +392,7 @@
LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
$(LIBX_OTHER) $(LIBSOUND) \
$(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_CLOCK_GETTIME) \
- $(LIB_EACCESS) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
+ $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
$(LIB_EXECINFO) \
$(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \
$(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
=== modified file 'src/conf_post.h'
--- src/conf_post.h 2013-02-01 06:30:51 +0000
+++ src/conf_post.h 2013-03-13 05:52:50 +0000
@@ -44,19 +44,6 @@
# define __has_attribute(a) 0 /* non-clang */
#endif
-/* This silences a few compilation warnings on FreeBSD. */
-#ifdef BSD_SYSTEM_AHB
-#undef BSD_SYSTEM_AHB
-#undef BSD_SYSTEM
-#if __FreeBSD__ == 1
-#define BSD_SYSTEM 199103
-#elif __FreeBSD__ == 2
-#define BSD_SYSTEM 199306
-#elif __FreeBSD__ >= 3
-#define BSD_SYSTEM 199506
-#endif
-#endif
-
#ifdef DARWIN_OS
#ifdef emacs
#define malloc unexec_malloc
=== modified file 'src/fileio.c'
--- src/fileio.c 2013-03-13 07:27:34 +0000
+++ src/fileio.c 2013-03-13 07:31:15 +0000
@@ -4959,20 +4959,23 @@
immediate_quit = 0;
-#ifdef HAVE_FSYNC
/* fsync appears to change the modtime on BSD4.2.
Disk full in NFS may be reported here. */
/* mib says that closing the file will try to write as fast as NFS can do
it, and that means the fsync here is not crucial for autosave files. */
- if (!auto_saving && !write_region_inhibit_fsync && fsync (desc) < 0)
+ if (!auto_saving && !write_region_inhibit_fsync)
{
- /* If fsync fails with EINTR, don't treat that as serious. Also
+ /* Transfer data and metadata to disk, retrying if interrupted. Also,
ignore EINVAL which happens when fsync is not supported on this
file. */
- if (errno != EINTR && errno != EINVAL)
- ok = 0, save_errno = errno;
+ while (fsync (desc) != 0)
+ if (errno != EINTR)
+ {
+ if (errno != EINVAL)
+ ok = 0, save_errno = errno;
+ break;
+ }
}
-#endif
modtime = invalid_emacs_time ();
if (visiting)
@@ -6046,13 +6049,11 @@
file is usually more useful if it contains the deleted text. */);
Vauto_save_include_big_deletions = Qnil;
-#ifdef HAVE_FSYNC
DEFVAR_BOOL ("write-region-inhibit-fsync", write_region_inhibit_fsync,
doc: /* Non-nil means don't call fsync in `write-region'.
This variable affects calls to `write-region' as well as save commands.
A non-nil value may result in data loss! */);
write_region_inhibit_fsync = 0;
-#endif
DEFVAR_BOOL ("delete-by-moving-to-trash", delete_by_moving_to_trash,
doc: /* Specifies whether to use the system's trash can.
=== modified file 'src/filelock.c'
--- src/filelock.c 2013-03-05 22:35:41 +0000
+++ src/filelock.c 2013-03-13 05:23:47 +0000
@@ -437,6 +437,14 @@
if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len
|| (need_fchmod && fchmod (fd, world_readable) != 0))
err = errno;
+ else
+ while (fsync (fd) != 0)
+ if (errno != EINTR)
+ {
+ if (errno != EINVAL)
+ err = errno;
+ break;
+ }
if (emacs_close (fd) != 0)
err = errno;
if (!err && rename_lock_file (nonce, lfname, force) != 0)
=== modified file 'src/sysdep.c'
--- src/sysdep.c 2013-03-13 05:04:46 +0000
+++ src/sysdep.c 2013-03-13 05:23:47 +0000
@@ -1289,10 +1289,9 @@
if (tty_out->terminal->reset_terminal_modes_hook)
tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal);
-#ifdef BSD_SYSTEM
/* Avoid possible loss of output when changing terminal modes. */
- fsync (fileno (tty_out->output));
-#endif
+ while (fdatasync (fileno (tty_out->output)) != 0 && errno == EINTR)
+ continue;
#ifndef DOS_NT
#ifdef F_SETOWN
next reply other threads:[~2013-03-13 7:38 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-03-13 7:38 Paul Eggert [this message]
2013-03-13 18:02 ` bug#13944: file synchronization fixes Eli Zaretskii
2013-03-13 18:43 ` Paul Eggert
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=51402CD8.1050005@cs.ucla.edu \
--to=eggert@cs.ucla.edu \
--cc=13944@debbugs.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).