Be smarter about releasing lockfiles

If KiCad crashes or exits without deleting the lockfile, don't show the
warning message unless we are not the one who locked it or there are
other KiCad instances running locally.

This should catch 99% of the cases where the message is shown
incorrectly.  There may be some corner cases where the lock file is
created on a network drive using two different machines with the same
name and same user but these cases should be (famous last words)
sufficiently rare as to not be observed in practice
This commit is contained in:
Seth Hillbrand 2023-07-21 15:40:19 -07:00
parent e71422d2cf
commit 7fe83993cf
8 changed files with 47 additions and 5 deletions

View File

@ -155,7 +155,7 @@ long KIDIALOG::getStyle( KD_TYPE aType )
}
bool OverrideLock( wxWindow* aParent, const wxString& aMessage )
bool AskOverrideLock( wxWindow* aParent, const wxString& aMessage )
{
#ifdef __APPLE__
// wxMessageDialog gets the button spacing wrong on Mac so we have to use wxRichMessageDialog.

View File

@ -226,6 +226,15 @@ bool EDA_DRAW_FRAME::LockFile( const wxString& aFileName )
m_file_checker = std::make_unique<LOCKFILE>( aFileName );
if( !m_file_checker->Valid() && m_file_checker->IsLockedByMe() )
{
// If we cannot acquire the lock but we appear to be the one who
// locked it, check to see if there is another KiCad instance running.
// If there is not, then we can override the lock. This could happen if
// KiCad crashed or was interrupted
if( !Pgm().SingleInstance()->IsAnotherRunning() )
m_file_checker->OverrideLock();
}
// If the file is valid, return true. This could mean that the file is
// locked or it could mean that the file is read-only
return m_file_checker->Valid();

View File

@ -166,6 +166,8 @@ void PGM_BASE::Destroy()
// unlike a normal destructor, this is designed to be called more than once safely:
delete m_locale;
m_locale = nullptr;
m_pgm_checker.reset();
}
@ -470,6 +472,8 @@ bool PGM_BASE::InitPgm( bool aHeadless, bool aSkipPyInit, bool aIsUnitTest )
return false;
}
#endif
m_pgm_checker = std::make_unique<wxSingleInstanceChecker>();
m_pgm_checker->Create( pgm_name, wxStandardPaths::Get().GetTempDir() );
// Init KiCad environment
// the environment variable KICAD (if exists) gives the kicad path:

View File

@ -108,7 +108,7 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
msg.Printf( _( "Schematic '%s' is already open by '%s' at '%s'." ), fullFileName,
m_file_checker->GetUsername(), m_file_checker->GetHostname() );
if( !OverrideLock( this, msg ) )
if( !AskOverrideLock( this, msg ) )
return false;
m_file_checker->OverrideLock();

View File

@ -86,7 +86,7 @@ protected:
* Display a dialog indicating the file is already open, with an option to reset the lock.
* @return true if the lock was reset.
*/
bool OverrideLock( wxWindow* aParent, const wxString& aMessage );
bool AskOverrideLock( wxWindow* aParent, const wxString& aMessage );
/**

View File

@ -208,6 +208,11 @@ public:
return true;
}
bool IsLockedByMe()
{
return m_username == wxGetUserId() && m_hostname == wxGetHostName();
}
/**
* @return Current username. If we own the lock, this is us. Otherwise, this is the user that does own it
*/

View File

@ -38,11 +38,11 @@
#include <search_stack.h>
#include <settings/environment.h>
#include <wx/filename.h>
#include <wx/snglinst.h>
#undef pid_t
#include <pybind11/embed.h>
class wxSingleInstanceChecker;
class wxApp;
class wxMenu;
class wxWindow;
@ -357,6 +357,14 @@ public:
void ShowSplash();
void HideSplash();
/**
* Allows access to the wxSingleInstanceChecker to test for other running KiCads
*/
std::unique_ptr<wxSingleInstanceChecker>& SingleInstance()
{
return m_pgm_checker;
}
/**
* wxWidgets on MSW tends to crash if you spool up more than one print job at a time.
*/
@ -391,6 +399,10 @@ protected:
std::unique_ptr<SCRIPTING> m_python_scripting;
/// Checks if there is another copy of Kicad running at the same time
std::unique_ptr<wxSingleInstanceChecker> m_pgm_checker;
wxString m_bin_dir; /// full path to this program
wxString m_kicad_env; /// The KICAD system environment variable.

View File

@ -49,6 +49,7 @@
#include <widgets/wx_progress_reporters.h>
#include <settings/settings_manager.h>
#include <paths.h>
#include <pgm_base.h>
#include <project/project_file.h>
#include <project/project_local_settings.h>
#include <project/net_settings.h>
@ -606,12 +607,23 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
std::unique_ptr<LOCKFILE> lock = std::make_unique<LOCKFILE>( fullFileName );
if( !lock->Valid() && lock->IsLockedByMe() )
{
// If we cannot acquire the lock but we appear to be the one who
// locked it, check to see if there is another KiCad instance running.
// If there is not, then we can override the lock. This could happen if
// KiCad crashed or was interrupted
if( !Pgm().SingleInstance()->IsAnotherRunning() )
lock->OverrideLock();
}
if( !lock->Valid() )
{
msg.Printf( _( "PCB '%s' is already open by '%s' at '%s'." ), wx_filename.GetFullName(),
lock->GetUsername(), lock->GetHostname() );
if( !OverrideLock( this, msg ) )
if( !AskOverrideLock( this, msg ) )
return false;
lock->OverrideLock();