From 15d9751919c6937e537fb85f2dca63fca2aaa892 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 17 Feb 2021 09:38:00 +0100 Subject: [PATCH] Delete lockfile at shutdown on linux and mac. Passing lockfile on mac by sending message . --- src/slic3r/GUI/InstanceCheck.cpp | 86 ++++++++++++++++++++++-------- src/slic3r/GUI/InstanceCheck.hpp | 6 +++ src/slic3r/GUI/InstanceCheckMac.h | 1 + src/slic3r/GUI/InstanceCheckMac.mm | 18 +++++++ 4 files changed, 89 insertions(+), 22 deletions(-) diff --git a/src/slic3r/GUI/InstanceCheck.cpp b/src/slic3r/GUI/InstanceCheck.cpp index 73bbeda35..9535e0126 100644 --- a/src/slic3r/GUI/InstanceCheck.cpp +++ b/src/slic3r/GUI/InstanceCheck.cpp @@ -28,8 +28,32 @@ #endif //__linux__ namespace Slic3r { + +#ifdef __APPLE__ + bool unlock_lockfile(const std::string& name, const std::string& path) + { + std::string dest_dir = path + name; + //BOOST_LOG_TRIVIAL(debug) << "full lock path: " << dest_dir; + struct flock fl; + int fdlock; + fl.l_type = F_UNLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 1; + if ((fdlock = open(dest_dir.c_str(), O_WRONLY | O_CREAT, 0666)) == -1) + return false; + + if (fcntl(fdlock, F_SETLK, &fl) == -1) + return false; + + return true; + } +#endif //__APPLE__ + namespace instance_check_internal { + static bool s_created_lockfile = false; + struct CommandLineAnalysis { std::optional should_send; @@ -145,15 +169,41 @@ namespace instance_check_internal BOOST_LOG_TRIVIAL(debug) << "get_lock(): unable to create datadir !!!"; } - if ((fdlock = open(dest_dir.c_str(), O_WRONLY | O_CREAT, 0666)) == -1) + if ((fdlock = open(dest_dir.c_str(), O_WRONLY | O_CREAT, 0666)) == -1) { + BOOST_LOG_TRIVIAL(debug) << "Not creating lockfile."; return true; + } - if (fcntl(fdlock, F_SETLK, &fl) == -1) + if (fcntl(fdlock, F_SETLK, &fl) == -1) { + BOOST_LOG_TRIVIAL(debug) << "Not creating lockfile."; return true; + } + BOOST_LOG_TRIVIAL(debug) << "Creating lockfile."; + s_created_lockfile = true; return false; } + // Deletes lockfile if it was created by this instance + // The Lockfile is created only on Linux a OSX. On Win, its handled by named mutex. + // The lockfile is deleted by instance it created it. + // On OSX message is passed to other instances to create a new lockfile after deletition. + static void delete_lockfile() + { + //BOOST_LOG_TRIVIAL(debug) << "shuting down with lockfile: " << l_created_lockfile; + if (s_created_lockfile) + { + std::string path = data_dir() + "/cache/" + GUI::wxGetApp().get_instance_hash_string() + ".lock"; + if( remove( path.c_str() ) != 0 ) + BOOST_LOG_TRIVIAL(error) << "Failed to delete lockfile " << path; + //else + // BOOST_LOG_TRIVIAL(error) << "success delete lockfile " << path; +#ifdef __APPLE__ + send_message_mac_closing(GUI::wxGetApp().get_instance_hash_string(),GUI::wxGetApp().get_instance_hash_string()); +#endif + } + } + #endif //WIN32 #if defined(__APPLE__) @@ -295,7 +345,7 @@ bool instance_check(int argc, char** argv, bool app_config_single_instance) if (! cla.should_send.has_value()) cla.should_send = app_config_single_instance; #ifdef _WIN32 - GUI::wxGetApp().init_single_instance_checker(lock_name + ".lock", data_dir() + "/cache/"); + GUI::wxGetApp().init_single_instance_checker(lock_name + ".lock", data_dir() + "\\cache\\"); if (cla.should_send.value() && GUI::wxGetApp().single_instance_checker()->IsAnotherRunning()) { #else // mac & linx // get_lock() creates the lockfile therefore *cla.should_send is checked after @@ -306,29 +356,11 @@ bool instance_check(int argc, char** argv, bool app_config_single_instance) return true; } BOOST_LOG_TRIVIAL(info) << "instance check: Another instance not found or single-instance not set."; + return false; } -#ifdef __APPLE__ -bool unlock_lockfile(const std::string& name, const std::string& path) -{ - std::string dest_dir = path + name; - //BOOST_LOG_TRIVIAL(debug) << "full lock path: " << dest_dir; - struct flock fl; - int fdlock; - fl.l_type = F_UNLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 1; - if ((fdlock = open(dest_dir.c_str(), O_WRONLY | O_CREAT, 0666)) == -1) - return false; - if (fcntl(fdlock, F_SETLK, &fl) == -1) - return false; - - return true; -} -#endif //__APPLE__ namespace GUI { wxDEFINE_EVENT(EVT_LOAD_MODEL_OTHER_INSTANCE, LoadFromOtherInstanceEvent); @@ -355,6 +387,9 @@ void OtherInstanceMessageHandler::init(wxEvtHandler* callback_evt_handler) void OtherInstanceMessageHandler::shutdown(MainFrame* main_frame) { BOOST_LOG_TRIVIAL(debug) << "message handler shutdown()."; +#ifndef _WIN32 + instance_check_internal::delete_lockfile(); +#endif //!_WIN32 assert(m_initialized); if (m_initialized) { #ifdef _WIN32 @@ -472,6 +507,13 @@ void OtherInstanceMessageHandler::handle_message(const std::string& message) } } +#ifdef __APPLE__ +void OtherInstanceMessageHandler::handle_message_other_closed() +{ + instance_check_internal::get_lock(wxGetApp().get_instance_hash_string() + ".lock", data_dir() + "/cache/"); +} +#endif //__APPLE__ + #ifdef BACKGROUND_MESSAGE_LISTENER namespace MessageHandlerDBusInternal diff --git a/src/slic3r/GUI/InstanceCheck.hpp b/src/slic3r/GUI/InstanceCheck.hpp index 9fb74b0a9..907b83192 100644 --- a/src/slic3r/GUI/InstanceCheck.hpp +++ b/src/slic3r/GUI/InstanceCheck.hpp @@ -28,6 +28,8 @@ bool instance_check(int argc, char** argv, bool app_config_single_instance); // apple implementation of inner functions of instance_check // in InstanceCheckMac.mm void send_message_mac(const std::string& msg, const std::string& version); +void send_message_mac_closing(const std::string& msg, const std::string& version); + bool unlock_lockfile(const std::string& name, const std::string& path); #endif //__APPLE__ @@ -66,6 +68,10 @@ public: // mac - anybody who posts notification with name:@"OtherPrusaSlicerTerminating" // linux - instrospectable on dbus void handle_message(const std::string& message); +#ifdef __APPLE__ + // Messege form other instance, that it deleted its lockfile - first instance to get it will create its own. + void handle_message_other_closed(); +#endif //__APPLE__ #ifdef _WIN32 static void init_windows_properties(MainFrame* main_frame, size_t instance_hash); #endif //WIN32 diff --git a/src/slic3r/GUI/InstanceCheckMac.h b/src/slic3r/GUI/InstanceCheckMac.h index 30943c4d5..0af2737ef 100644 --- a/src/slic3r/GUI/InstanceCheckMac.h +++ b/src/slic3r/GUI/InstanceCheckMac.h @@ -5,5 +5,6 @@ -(instancetype) init; -(void) add_observer:(NSString *)version; -(void) message_update:(NSNotification *)note; +-(void) closing_update:(NSNotification *)note; -(void) bring_forward; @end diff --git a/src/slic3r/GUI/InstanceCheckMac.mm b/src/slic3r/GUI/InstanceCheckMac.mm index 1d6f244e8..b43e898b0 100644 --- a/src/slic3r/GUI/InstanceCheckMac.mm +++ b/src/slic3r/GUI/InstanceCheckMac.mm @@ -15,6 +15,8 @@ //NSString *nsver = @"OtherPrusaSlicerInstanceMessage" + version_hash; NSString *nsver = [NSString stringWithFormat: @"%@%@", @"OtherPrusaSlicerInstanceMessage", version_hash]; [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(message_update:) name:nsver object:nil suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately]; + NSString *nsver2 = [NSString stringWithFormat: @"%@%@", @"OtherPrusaSlicerInstanceClosing", version_hash]; + [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(closing_update:) name:nsver2 object:nil suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately]; } -(void)message_update:(NSNotification *)msg @@ -24,6 +26,13 @@ Slic3r::GUI::wxGetApp().other_instance_message_handler()->handle_message(std::string([msg.userInfo[@"data"] UTF8String])); } +-(void)closing_update:(NSNotification *)msg +{ + //[self bring_forward]; + //pass message + Slic3r::GUI::wxGetApp().other_instance_message_handler()->handle_message_other_closed(); +} + -(void) bring_forward { //demiaturize all windows @@ -51,6 +60,15 @@ void send_message_mac(const std::string &msg, const std::string &version) [[NSDistributedNotificationCenter defaultCenter] postNotificationName:notifname object:nil userInfo:[NSDictionary dictionaryWithObject:nsmsg forKey:@"data"] deliverImmediately:YES]; } +void send_message_mac_closing(const std::string &msg, const std::string &version) +{ + NSString *nsmsg = [NSString stringWithCString:msg.c_str() encoding:[NSString defaultCStringEncoding]]; + //NSString *nsver = @"OtherPrusaSlicerInstanceMessage" + [NSString stringWithCString:version.c_str() encoding:[NSString defaultCStringEncoding]]; + NSString *nsver = [NSString stringWithCString:version.c_str() encoding:[NSString defaultCStringEncoding]]; + NSString *notifname = [NSString stringWithFormat: @"%@%@", @"OtherPrusaSlicerInstanceClosing", nsver]; + [[NSDistributedNotificationCenter defaultCenter] postNotificationName:notifname object:nil userInfo:[NSDictionary dictionaryWithObject:nsmsg forKey:@"data"] deliverImmediately:YES]; +} + namespace GUI { void OtherInstanceMessageHandler::register_for_messages(const std::string &version_hash) {