Windows: improve indexing process management. Fix Pidfile locking.

Use a stop file to request stop of indexing when the indexer was not
started from the current GUI instance.
This commit is contained in:
Jean-Francois Dockes
2019-02-14 14:12:08 +01:00
parent 0e866f1bce
commit 8853cb505a
5 changed files with 181 additions and 17 deletions
+165 -8
View File
@@ -13,6 +13,30 @@
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* flock emulation:
* Emulate flock on platforms that lack it, primarily Windows and MinGW.
*
* This is derived from sqlite3 sources.
* https://www.sqlite.org/src/finfo?name=src/os_win.c
* https://www.sqlite.org/copyright.html
*
* Written by Richard W.M. Jones <rjones.at.redhat.com>
*
* Copyright (C) 2008-2019 Free Software Foundation, Inc.
*
* This 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.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifdef BUILDING_RECOLL
@@ -105,7 +129,144 @@ static bool path_isdriveabs(const string& s)
}
return false;
}
#endif
/* Operations for the 'flock' call (same as Linux kernel constants). */
# define LOCK_SH 1 /* Shared lock. */
# define LOCK_EX 2 /* Exclusive lock. */
# define LOCK_UN 8 /* Unlock. */
/* Can be OR'd in to one of the above. */
# define LOCK_NB 4 /* Don't block when locking. */
#include <io.h>
/* Determine the current size of a file. Because the other braindead
* APIs we'll call need lower/upper 32 bit pairs, keep the file size
* like that too.
*/
static BOOL
file_size (HANDLE h, DWORD * lower, DWORD * upper)
{
*lower = GetFileSize (h, upper);
/* It appears that we can't lock an empty file, a lock is always
over a data section. But we seem to be able to set a lock
beyond the current file size, which is enough to get Pidfile
working */
if (*lower == 0 && *upper == 0) {
*lower = 100;
}
return 1;
}
/* LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. */
# ifndef LOCKFILE_FAIL_IMMEDIATELY
# define LOCKFILE_FAIL_IMMEDIATELY 1
# endif
/* Acquire a lock. */
static BOOL
do_lock (HANDLE h, int non_blocking, int exclusive)
{
BOOL res;
DWORD size_lower, size_upper;
OVERLAPPED ovlp;
int flags = 0;
/* We're going to lock the whole file, so get the file size. */
res = file_size (h, &size_lower, &size_upper);
if (!res)
return 0;
/* Start offset is 0, and also zero the remaining members of this struct. */
memset (&ovlp, 0, sizeof ovlp);
if (non_blocking)
flags |= LOCKFILE_FAIL_IMMEDIATELY;
if (exclusive)
flags |= LOCKFILE_EXCLUSIVE_LOCK;
return LockFileEx (h, flags, 0, size_lower, size_upper, &ovlp);
}
/* Unlock reader or exclusive lock. */
static BOOL
do_unlock (HANDLE h)
{
int res;
DWORD size_lower, size_upper;
res = file_size (h, &size_lower, &size_upper);
if (!res)
return 0;
return UnlockFile (h, 0, 0, size_lower, size_upper);
}
/* Now our BSD-like flock operation. */
int
flock (int fd, int operation)
{
HANDLE h = (HANDLE) _get_osfhandle (fd);
DWORD res;
int non_blocking;
if (h == INVALID_HANDLE_VALUE) {
errno = EBADF;
return -1;
}
non_blocking = operation & LOCK_NB;
operation &= ~LOCK_NB;
switch (operation) {
case LOCK_SH:
res = do_lock (h, non_blocking, 0);
break;
case LOCK_EX:
res = do_lock (h, non_blocking, 1);
break;
case LOCK_UN:
res = do_unlock (h);
break;
default:
errno = EINVAL;
return -1;
}
/* Map Windows errors into Unix errnos. As usual MSDN fails to
* document the permissible error codes.
*/
if (!res) {
DWORD err = GetLastError ();
switch (err){
/* This means someone else is holding a lock. */
case ERROR_LOCK_VIOLATION:
errno = EAGAIN;
break;
/* Out of memory. */
case ERROR_NOT_ENOUGH_MEMORY:
errno = ENOMEM;
break;
case ERROR_BAD_COMMAND:
errno = EINVAL;
break;
/* Unlikely to be other errors, but at least don't lose the
* error code.
*/
default:
errno = err;
}
return -1;
}
return 0;
}
#endif // Win32 only section
bool fsocc(const string& path, int *pc, long long *avmbs)
{
@@ -931,14 +1092,14 @@ pid_t Pidfile::read_pid()
{
int fd = ::open(m_path.c_str(), O_RDONLY);
if (fd == -1) {
return (pid_t) - 1;
return (pid_t) -1;
}
char buf[16];
int i = read(fd, buf, sizeof(buf) - 1);
::close(fd);
if (i <= 0) {
return (pid_t) - 1;
return (pid_t) -1;
}
buf[i] = '\0';
char *endptr;
@@ -967,12 +1128,9 @@ int Pidfile::flopen()
int serrno = errno;
this->close()
errno = serrno;
m_reason = "fcntl lock failed";
m_reason = "fcntl lock failed";
return -1;
}
#else
#ifdef _WIN32
return 0;
#else
int operation = LOCK_EX | LOCK_NB;
if (flock(m_fd, operation) == -1) {
@@ -982,7 +1140,6 @@ int Pidfile::flopen()
m_reason = "flock failed";
return -1;
}
#endif // ! win32
#endif // ! sun
if (ftruncate(m_fd, 0) != 0) {