Index: backends/chert/chert_database.cc
===================================================================
--- backends/chert/chert_database.cc	(revision 15321)
+++ backends/chert/chert_database.cc	(working copy)
@@ -538,12 +538,16 @@
     filepath += '/';
     for (const char * p = filenames; *p; p += *p + 1) {
 	string leaf(p + 1, size_t(static_cast<unsigned char>(*p)));
-        filepath.replace(db_dir.size() + 1, string::npos, leaf);
-	if (file_exists(filepath)) {
-	    // FIXME - there is a race condition here - the file might get
-	    // deleted between the file_exists() test and the access to send it.
+	filepath.replace(db_dir.size() + 1, string::npos, leaf);
+#ifdef __WIN32__
+	int fd = msvc_posix_open(filepath.c_str(), O_RDONLY);
+#else
+	int fd = open(filepath.c_str(), O_RDONLY);
+#endif
+	if (fd > 0) {
+	    fdcloser closefd(fd);
 	    conn.send_message(REPL_REPLY_DB_FILENAME, leaf, end_time);
-	    conn.send_file(REPL_REPLY_DB_FILEDATA, filepath, end_time);
+	    conn.send_file(REPL_REPLY_DB_FILEDATA, fd, end_time);
 	}
     }
 }
@@ -640,7 +644,14 @@
 
 	    // Look for the changeset for revision start_rev_num.
 	    string changes_name = db_dir + "/changes" + str(start_rev_num);
-	    if (file_exists(changes_name)) {
+#ifdef __WIN32__
+	    int fd_changes = msvc_posix_open(changes_name.c_str(), O_RDONLY);
+#else
+	    int fd_changes = open(changes_name.c_str(), O_RDONLY);
+#endif
+	    if (fd_changes > 0) {
+		fdcloser closefd(fd_changes);
+
 		// Send it, and also update start_rev_num to the new value
 		// specified in the changeset.
 		chert_revision_number_t changeset_start_rev_num;
@@ -654,10 +665,8 @@
 		if (changeset_start_rev_num >= changeset_end_rev_num) {
 		    throw Xapian::DatabaseError("Changeset start revision is not less than end revision");
 		}
-		// FIXME - there is a race condition here - the file might get
-		// deleted between the file_exists() test and the access to
-		// send it.
-		conn.send_file(REPL_REPLY_CHANGESET, changes_name, 0.0);
+
+		conn.send_file(REPL_REPLY_CHANGESET, fd_changes, 0.0);
 		start_rev_num = changeset_end_rev_num;
 		if (info != NULL) {
 		    ++(info->changeset_count);
Index: backends/brass/brass_database.cc
===================================================================
--- backends/brass/brass_database.cc	(revision 15322)
+++ backends/brass/brass_database.cc	(working copy)
@@ -543,12 +543,16 @@
     filepath += '/';
     for (const char * p = filenames; *p; p += *p + 1) {
 	string leaf(p + 1, size_t(static_cast<unsigned char>(*p)));
-        filepath.replace(db_dir.size() + 1, string::npos, leaf);
-	if (file_exists(filepath)) {
-	    // FIXME - there is a race condition here - the file might get
-	    // deleted between the file_exists() test and the access to send it.
+	filepath.replace(db_dir.size() + 1, string::npos, leaf);
+#ifdef __WIN32__
+	int fd = msvc_posix_open(filepath.c_str(), O_RDONLY);
+#else
+	int fd = open(filepath.c_str(), O_RDONLY);
+#endif
+	if (fd > 0) {
+	    fdcloser closefd(fd);
 	    conn.send_message(REPL_REPLY_DB_FILENAME, leaf, end_time);
-	    conn.send_file(REPL_REPLY_DB_FILEDATA, filepath, end_time);
+	    conn.send_file(REPL_REPLY_DB_FILEDATA, fd, end_time);
 	}
     }
 }
@@ -645,7 +649,14 @@
 
 	    // Look for the changeset for revision start_rev_num.
 	    string changes_name = db_dir + "/changes" + str(start_rev_num);
-	    if (file_exists(changes_name)) {
+#ifdef __WIN32__
+	    int fd_changes = msvc_posix_open(changes_name.c_str(), O_RDONLY);
+#else
+	    int fd_changes = open(changes_name.c_str(), O_RDONLY);
+#endif
+	    if (fd_changes > 0) {
+		fdcloser closefd(fd_changes);
+
 		// Send it, and also update start_rev_num to the new value
 		// specified in the changeset.
 		brass_revision_number_t changeset_start_rev_num;
@@ -659,10 +670,8 @@
 		if (changeset_start_rev_num >= changeset_end_rev_num) {
 		    throw Xapian::DatabaseError("Changeset start revision is not less than end revision");
 		}
-		// FIXME - there is a race condition here - the file might get
-		// deleted between the file_exists() test and the access to
-		// send it.
-		conn.send_file(REPL_REPLY_CHANGESET, changes_name, 0.0);
+
+		conn.send_file(REPL_REPLY_CHANGESET, fd_changes, 0.0);
 		start_rev_num = changeset_end_rev_num;
 		if (info != NULL) {
 		    ++(info->changeset_count);
Index: backends/flint/flint_database.cc
===================================================================
--- backends/flint/flint_database.cc	(revision 15269)
+++ backends/flint/flint_database.cc	(working copy)
@@ -575,12 +575,16 @@
     filepath += '/';
     for (const char * p = filenames; *p; p += *p + 1) {
 	string leaf(p + 1, size_t(static_cast<unsigned char>(*p)));
-        filepath.replace(db_dir.size() + 1, string::npos, leaf);
-	if (file_exists(filepath)) {
-	    // FIXME - there is a race condition here - the file might get
-	    // deleted between the file_exists() test and the access to send it.
+	filepath.replace(db_dir.size() + 1, string::npos, leaf);
+#ifdef __WIN32__
+	int fd = msvc_posix_open(filepath.c_str(), O_RDONLY);
+#else
+	int fd = open(filepath.c_str(), O_RDONLY);
+#endif
+	if (fd > 0) {
+	    fdcloser closefd(fd);
 	    conn.send_message(REPL_REPLY_DB_FILENAME, leaf, end_time);
-	    conn.send_file(REPL_REPLY_DB_FILEDATA, filepath, end_time);
+	    conn.send_file(REPL_REPLY_DB_FILEDATA, fd, end_time);
 	}
     }
 }
@@ -677,7 +681,14 @@
 
 	    // Look for the changeset for revision start_rev_num.
 	    string changes_name = db_dir + "/changes" + str(start_rev_num);
-	    if (file_exists(changes_name)) {
+#ifdef __WIN32__
+	    int fd_changes = msvc_posix_open(changes_name.c_str(), O_RDONLY);
+#else
+	    int fd_changes = open(changes_name.c_str(), O_RDONLY);
+#endif
+	    if (fd_changes > 0) {
+		fdcloser closefd(fd_changes);
+
 		// Send it, and also update start_rev_num to the new value
 		// specified in the changeset.
 		flint_revision_number_t changeset_start_rev_num;
@@ -691,10 +702,8 @@
 		if (changeset_start_rev_num >= changeset_end_rev_num) {
 		    throw Xapian::DatabaseError("Changeset start revision is not less than end revision");
 		}
-		// FIXME - there is a race condition here - the file might get
-		// deleted between the file_exists() test and the access to
-		// send it.
-		conn.send_file(REPL_REPLY_CHANGESET, changes_name, 0.0);
+
+		conn.send_file(REPL_REPLY_CHANGESET, fd_changes, 0.0);
 		start_rev_num = changeset_end_rev_num;
 		if (info != NULL) {
 		    ++(info->changeset_count);
Index: common/remoteconnection.h
===================================================================
--- common/remoteconnection.h	(revision 15269)
+++ common/remoteconnection.h	(working copy)
@@ -260,13 +260,13 @@
     /** Send the contents of a file as a message.
      *
      *  @param type		Message type code.
-     *  @param file		Path to file containing the Message data.
+     *  @param fd		File containing the message data.
      *  @param end_time		If this time is reached, then a timeout
      *				exception will be thrown.  If
      *				(end_time == 0.0) then the operation will
      *				never timeout.
      */
-    void send_file(char type, const std::string &file, double end_time);
+    void send_file(char type, int fd, double end_time);
 
     /** Shutdown the connection.
      *
Index: net/remoteconnection.cc
===================================================================
--- net/remoteconnection.cc	(revision 15269)
+++ net/remoteconnection.cc	(working copy)
@@ -315,26 +315,18 @@
 }
 
 void
-RemoteConnection::send_file(char type, const string &file, double end_time)
+RemoteConnection::send_file(char type, int fd, double end_time)
 {
-    LOGCALL_VOID(REMOTE, "RemoteConnection::send_file", type | file | end_time);
+    LOGCALL_VOID(REMOTE, "RemoteConnection::send_file", type | fd | end_time);
     if (fdout == -1) {
 	throw Xapian::DatabaseError("Database has been closed");
     }
 
-#ifdef __WIN32__
-    int fd = msvc_posix_open(file.c_str(), O_RDONLY);
-#else
-    int fd = open(file.c_str(), O_RDONLY);
-#endif
-    if (fd == -1) throw Xapian::NetworkError("File not found: " + file, errno);
-    fdcloser closefd(fd);
-
     off_t size;
     {
 	struct stat sb;
 	if (fstat(fd, &sb) == -1)
-	    throw Xapian::NetworkError("Couldn't stat file: " + file, errno);
+	    throw Xapian::NetworkError("Couldn't stat file to send", errno);
 	size = sb.st_size;
     }
     // FIXME: Use sendfile() or similar if available?

