← Back to team overview

kicad-developers team mailing list archive

[PATCH] Fix lockfile placement on Linux/OSX

 

Hello, I wrote a patch to fix the issue of Kicad creating lock/PID
files for applications and open files in the user's home directory,
which is unsightly and wrong according to the XDG[1]/Apple[2]
standards/spec.

To fix it I created a new function in common.cpp which fetches the
proper path to use using environment variables and a couple fallbacks,
and edited all calls to wxSingleInstanceChecker's constructor to use
it. According to wxwidgets's documentation [3] the constructor
*should* ignore that extra argument on windows since it uses mutexes
instead of lock files. In Mac OSX I used the standard user-specific
cache directory, choosing somewhat arbitrarily "org.kicad-pcb.kicad"
as the app bundle name, feel free to change it if you think something
else would suit better.

In any case, it does need testing in those platforms. It works as
expected on Debian Jessie.

[1]: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
[2]: https://developer.apple.com/library/mac/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/MacOSXDirectories/MacOSXDirectories.html#//apple_ref/doc/uid/TP40010672-CH10-SW1
[3]: http://docs.wxwidgets.org/trunk/classwx_single_instance_checker.html#aa69725041ea6c0479f65f6b468a42f1e
=== modified file 'common/common.cpp'
--- common/common.cpp	2014-12-23 13:01:59 +0000
+++ common/common.cpp	2015-01-05 06:56:25 +0000
@@ -305,6 +305,46 @@
     return cfg;
 }
 
+wxString GetKicadLockFilePath()
+{
+    wxFileName lockpath;
+    lockpath.AssignDir( wxGetHomeDir() ); // Default wx behavior
+
+#if defined( __WXMAC__ )
+    // In OSX use the standard per user cache directory
+    lockpath.AppendDir( wxT( "Library" ) );
+    lockpath.AppendDir( wxT( "Caches" ) );
+    lockparh.AppendDir( wxT( "org.kicad-pcb.kicad" ) );
+#elif defined( __UNIX__ )
+    wxString envstr;
+    // Try first the standard XDG_RUNTIME_DIR, falling back to XDG_CACHE_HOME
+    if (wxGetEnv( wxT( "XDG_RUNTIME_DIR" ), &envstr ) && !envstr.IsEmpty())
+    {
+        lockpath.AssignDir( envstr );
+    }
+    else if (wxGetEnv( wxT( "XDG_CACHE_HOME" ), &envstr ) && !envstr.IsEmpty())
+    {
+        lockpath.AssignDir( envstr );
+    }
+    else
+    {
+        // If all fails, just use ~/.cache
+        lockpath.AppendDir( wxT( ".cache" ) ); 
+    }
+
+    lockpath.AppendDir( wxT( "kicad" ) );
+#endif
+    
+#if defined( __WXMAC__ ) || defined( __UNIX__ )
+    if( !lockpath.DirExists() )
+    {
+	// Lockfiles should be only readable by the user
+        lockpath.Mkdir( 0700, wxPATH_MKDIR_FULL );
+    }
+#endif
+    return lockpath.GetPath();
+}
+
 
 wxString GetKicadConfigPath()
 {

=== modified file 'common/lockfile.cpp'
--- common/lockfile.cpp	2014-10-19 20:20:16 +0000
+++ common/lockfile.cpp	2015-01-05 04:00:09 +0000
@@ -24,6 +24,7 @@
 
 #include <wx/filename.h>
 #include <wx/snglinst.h>
+#include <common.h>
 
 
 wxSingleInstanceChecker* LockFile( const wxString& aFileName )
@@ -41,7 +42,7 @@
     // We can have filenames coming from Windows, so also convert Windows separator
     lockFileName.Replace( wxT( "\\" ), wxT( "_" ) );
 
-    wxSingleInstanceChecker* p = new wxSingleInstanceChecker( lockFileName );
+    wxSingleInstanceChecker* p = new wxSingleInstanceChecker( lockFileName, GetKicadLockFilePath() );
 
     if( p->IsAnotherRunning() )
     {

=== modified file 'common/pgm_base.cpp'
--- common/pgm_base.cpp	2014-10-17 17:45:33 +0000
+++ common/pgm_base.cpp	2015-01-05 03:31:13 +0000
@@ -353,7 +353,7 @@
 
     wxInitAllImageHandlers();
 
-    m_pgm_checker = new wxSingleInstanceChecker( pgm_name.GetName().Lower() + wxT( "-" ) + wxGetUserId() );
+    m_pgm_checker = new wxSingleInstanceChecker( pgm_name.GetName().Lower() + wxT( "-" ) + wxGetUserId(), GetKicadLockFilePath() );
 
     if( m_pgm_checker->IsAnotherRunning() )
     {

=== modified file 'include/common.h'
--- include/common.h	2014-12-23 13:01:59 +0000
+++ include/common.h	2015-01-05 03:29:04 +0000
@@ -434,6 +434,12 @@
 wxConfigBase* GetNewConfig( const wxString& aProgName );
 
 /**
+ * Function GetKicadLockFilePath
+ * @return A wxString containing the path for lockfiles in Kicad
+ */
+wxString GetKicadLockFilePath();
+
+/**
  * Function GetKicadConfigPath
  * @return A wxString containing the config path for Kicad
  */


Follow ups