From b0342fe8d376ff9c87093bd1bcad95de07db0467 Mon Sep 17 00:00:00 2001 From: micio Date: Sat, 1 Nov 2008 15:59:09 +0000 Subject: [PATCH] updated Signals package git-svn-id: svn://ultimatepp.org/upp/trunk@588 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- bazaar/Signals/Signals.cpp | 88 +++++++++++++++++++++++ bazaar/Signals/Signals.h | 21 ++++++ bazaar/Signals/src.tpp/TSignals$en-us.tpp | 47 ++++++++++++ bazaar/TestSignals/main.cpp | 16 ++++- 4 files changed, 171 insertions(+), 1 deletion(-) diff --git a/bazaar/Signals/Signals.cpp b/bazaar/Signals/Signals.cpp index cc02b0909..61f59d8b8 100644 --- a/bazaar/Signals/Signals.cpp +++ b/bazaar/Signals/Signals.cpp @@ -17,6 +17,8 @@ void _SignalHandler(int sig, siginfo_t *info, void *v) // constructor TSignals::TSignals() { + // not(yet) stored instance on file + StoredInstance = false; } // END Constructor TSignals @@ -37,6 +39,11 @@ TSignals::~TSignals() // empties the map CallbackMap.Clear(); + // if process had stored instance on file, removes it + if(StoredInstance) + FileDelete(CreateLockName()); + StoredInstance = false; + } // END Destructor class TSignals //////////////////////////////////////////////////////////////////////////////////// @@ -53,6 +60,17 @@ void TSignals::Dispatch(int sig, siginfo_t *info, void *v) } // END TSignals::Dispatcher() +//////////////////////////////////////////////////////////////////////////////////// +// creates lock file name based on user name, app name and display +String TSignals::CreateLockName(void) +{ + if(LockName == "") + LockName = "/tmp/" + Environment().Get("USER") + "_" + GetExeTitle() + "_" + Environment().Get("DISPLAY") + ".lck"; + + return LockName; + +} // END TSignals::CreateLockName() + //////////////////////////////////////////////////////////////////////////////////// // add a signal handler bool TSignals::Handle(int sig, Callback const &cb) @@ -107,6 +125,76 @@ bool TSignals::Unhandle(int sig) } // END TSignals::Unhandle() +//////////////////////////////////////////////////////////////////////////////////// +// stores process info on filesystem +// allowing other process to communicate with it +bool TSignals::StoreInstance(void) +{ + // if already stored, does nothing + if(StoredInstance) + return true; + + // first, checks if another instance is running + // if yes returns false (can't store more than 1 instance) + if(IsOtherInstanceRunning()) + return false; + + // creates lock file + FileOut f(CreateLockName()); + + // stores current process id on lock file + f.PutLine(AsString(getpid())); + f.Close(); + + // marks instance as already stored + StoredInstance = true; + + // all ok + return true; + +} // END TSignals::StoreInstance() + +//////////////////////////////////////////////////////////////////////////////////// +// checks whether another instance of this process is running +bool TSignals::IsOtherInstanceRunning(void) +{ + // if we stored THIS instance, no other is running + if(StoredInstance) + return false; + + // otherwise, check the lock file + if(FileExists(CreateLockName())) + return true; + return false; + +} // END TSignals::IsOtherInstanceRunning() + +//////////////////////////////////////////////////////////////////////////////////// +// sends a signal to another process +bool TSignals::Send(int sig, int procId) +{ + return (kill(procId, sig) == 0); + +} // END TSignals::Send() + +//////////////////////////////////////////////////////////////////////////////////// +// sends a signal to another running instance of this app +bool TSignals::Send(int sig) +{ + // if no other instance running, returns false + if(!IsOtherInstanceRunning()) + return false; + + // gets pid of other instance + FileIn f(CreateLockName()); + int pid = atoi(f.GetLine()); + f.Close(); + + // sends the signal to process + return Send(sig, pid); + +} // END TSignals::Send() + //////////////////////////////////////////////////////////////////////////////////// // Global signals access TSignals &Signals(void) diff --git a/bazaar/Signals/Signals.h b/bazaar/Signals/Signals.h index 046f88f06..4d18a6298 100644 --- a/bazaar/Signals/Signals.h +++ b/bazaar/Signals/Signals.h @@ -11,6 +11,11 @@ class TSignals friend void ::_SignalHandler(int, siginfo_t *, void *); private: + + // flag indicating that the process instance has been stored on file + bool StoredInstance; + String LockName; + // signal/handlers map ArrayMap CallbackMap; @@ -20,6 +25,9 @@ class TSignals // dispatch signals void Dispatch(int sig, siginfo_t *info, void *v); + // creates lock file name based on user name, app name and display + String CreateLockName(void); + public: // distruttore @@ -30,7 +38,20 @@ class TSignals // removes a signal handler bool Unhandle(int sig); + + // stores process info on filesystem + // allowing other process to communicate with it + bool StoreInstance(void); + + // checks whether another instance of this process is running + bool IsOtherInstanceRunning(void); + // sends a signal to another process + bool Send(int sig, int procId); + + // sends a signal to another running instance of this app + bool Send(int sig); + }; // END Class TSignals //////////////////////////////////////////////////////////////////////////////////// diff --git a/bazaar/Signals/src.tpp/TSignals$en-us.tpp b/bazaar/Signals/src.tpp/TSignals$en-us.tpp index be82f667b..20511bc73 100644 --- a/bazaar/Signals/src.tpp/TSignals$en-us.tpp +++ b/bazaar/Signals/src.tpp/TSignals$en-us.tpp @@ -126,6 +126,13 @@ behaviour:&] :: [s0; [2 File size limit exceeded]]}}&] [s0; &] [s4;%- &] +[s5;:Signals`(void`):%- [_^TSignals^ TSignals]_`&[* Signals]([@(0.0.255) void])&] +[s2; &] +[s2; Returns global TSignals object Used to acceass all package +functions&] +[s2; &] +[s4;%- &] +[s3;%- &] [s5;:TSignals`:`:Handle`(int`,Callback const`&`):%- [@(0.0.255) bool]_[* Handle]([@(0.0.255) i nt]_[*@3 sig], [_^Callback^ Callback]_[@(0.0.255) const]_`&[*@3 cb])&] [s0;%- &] @@ -153,4 +160,44 @@ handle the signal&] [s2; Example usage:&] [s0; &] [s2; -|-|Signals().Unhandle(SIGHUP);&] +[s4;%- &] +[s5;:TSignals`:`:StoreInstance`(void`):%- [@(0.0.255) bool]_[* StoreInstance]([@(0.0.255) v +oid])&] +[s2; &] +[s2; Stores current process info on file allowing check for other +instances&] +[s3;%- &] +[s6; [*/ Return value]-|boolean, true if the call succeeded&] +[s0; &] +[s2; Example usage:&] +[s0; &] +[s2; -|-|Signals().StoreInstance();&] +[s4;%- &] +[s5;:TSignals`:`:IsOtherInstanceRunning`(void`):%- [@(0.0.255) bool]_[* IsOtherInstanceRu +nning]([@(0.0.255) void])&] +[s2; &] +[s2; Checks wether another instance of this app is already running&] +[s3;%- &] +[s6; [*/ Return value]-|boolean, true another instance is running&] +[s0; &] +[s2; Example usage:&] +[s0; &] +[s2; -|-|Signals().IsOtherInstanceRunning();&] +[s3;%- &] +[s4;%- &] +[s5;:TSignals`:`:Send`(int`,int`):%- [@(0.0.255) bool]_[* Send]([@(0.0.255) int]_[*@3 sig], +[@(0.0.255) int]_[*@3 procId])&] +[s2; &] +[s2; Sends a signal to another process&] +[s0; &] +[s2; [%-*@3 sig] ..................................Posix signal number&] +[s2; [%-*@3 procId].............................Process id of target +process&] +[s3; &] +[s4;%- &] +[s5;:TSignals`:`:Send`(int`):%- [@(0.0.255) bool]_[* Send]([@(0.0.255) int]_[*@3 sig])&] +[s2; &] +[s2; Sends a signal to another instance of this application&] +[s0; &] +[s2; [%-*@3 sig] ..................................Posix signal number&] [s0; ] \ No newline at end of file diff --git a/bazaar/TestSignals/main.cpp b/bazaar/TestSignals/main.cpp index 58298155e..aa856e8cf 100644 --- a/bazaar/TestSignals/main.cpp +++ b/bazaar/TestSignals/main.cpp @@ -39,6 +39,20 @@ TestSignals::TestSignals() GUI_APP_MAIN { + // first checks if another app instance is running + if(Signals().IsOtherInstanceRunning()) + { + // sends to other instance a SIGHUP signal + Signals().Send(SIGHUP); + + // prompt and exit + PromptOK("Another app instance is already running!!!"); + return; + } + + // ok, no other instance, signals this one + Signals().StoreInstance(); + + // runs the application TestSignals().Run(); } -