Merge Simon Arlott's 'xml-locking-fixes' into maint.

This commit is contained in:
John Ralls 2021-09-06 15:22:49 -07:00
commit 901fea158f
2 changed files with 8 additions and 80 deletions

View File

@ -171,8 +171,11 @@ GncXmlBackend::session_end()
if (!m_linkfile.empty())
g_unlink (m_linkfile.c_str());
if (m_lockfd > 0)
if (m_lockfd != -1)
{
close (m_lockfd);
m_lockfd = -1;
}
if (!m_lockfile.empty())
{
@ -638,12 +641,13 @@ GncXmlBackend::get_file_lock ()
{
/* oops .. file is locked by another user .. */
set_error(ERR_BACKEND_LOCKED);
m_lockfile.clear();
return false;
}
m_lockfd = g_open (m_lockfile.c_str(), O_RDWR | O_CREAT | O_EXCL ,
S_IRUSR | S_IWUSR);
if (m_lockfd < 0)
if (m_lockfd == -1)
{
/* oops .. we can't create the lockfile .. */
switch (errno)
@ -661,87 +665,11 @@ GncXmlBackend::get_file_lock ()
PWARN ("Unable to create the lockfile %s: %s",
m_lockfile.c_str(), strerror(errno));
set_error(be_err);
m_lockfile.clear();
return false;
}
/* OK, now work around some NFS atomic lock race condition
* mumbo-jumbo. We do this by linking a unique file, and
* then examining the link count. At least that's what the
* NFS programmers guide suggests.
* Note: the "unique filename" must be unique for the
* triplet filename-host-process, otherwise accidental
* aliases can occur.
*/
/* apparently, even this code may not work for some NFS
* implementations. In the long run, I am told that
* ftp.debian.org
* /pub/debian/dists/unstable/main/source/libs/liblockfile_0.1-6.tar.gz
* provides a better long-term solution.
*/
#ifndef G_OS_WIN32
auto path = m_lockfile.find_last_of('.');
std::stringstream linkfile;
if (path != std::string::npos)
linkfile << m_lockfile.substr(0, path);
else
linkfile << m_lockfile;
linkfile << "." << gethostid() << "." << getpid() << ".LNK";
rc = link (m_lockfile.c_str(), linkfile.str().c_str());
if (rc)
{
/* If hard links aren't supported, just allow the lock. */
if (errno == EPERM || errno == ENOSYS
# ifdef EOPNOTSUPP
|| errno == EOPNOTSUPP
# endif
# ifdef ENOTSUP
|| errno == ENOTSUP
# endif
)
{
return true;
}
/* Otherwise, something else is wrong. */
set_error(ERR_BACKEND_LOCKED);
g_unlink (linkfile.str().c_str());
close (m_lockfd);
g_unlink (m_lockfile.c_str());
return false;
}
rc = g_stat (m_lockfile.c_str(), &statbuf);
if (rc)
{
/* oops .. stat failed! This can't happen! */
set_error(ERR_BACKEND_LOCKED);
std::string msg{"Failed to stat lockfile "};
set_message(msg + m_lockfile);
g_unlink (linkfile.str().c_str());
close (m_lockfd);
g_unlink (m_lockfile.c_str());
return false;
}
if (statbuf.st_nlink != 2)
{
set_error(ERR_BACKEND_LOCKED);
g_unlink (linkfile.str().c_str());
close (m_lockfd);
g_unlink (m_lockfile.c_str());
return false;
}
m_linkfile = linkfile.str();
return true;
#else /* ifndef G_OS_WIN32 */
/* On windows, there is no NFS and the open(,O_CREAT | O_EXCL)
is sufficient for locking. */
return true;
#endif /* ifndef G_OS_WIN32 */
}
bool

View File

@ -60,7 +60,7 @@ private:
std::string m_dirname;
std::string m_lockfile;
std::string m_linkfile;
int m_lockfd;
int m_lockfd = -1;
QofBook* m_book = nullptr; /* The primary, main open book */
};