I am using Qt and trying to achieve a single instance application by applying this solution in Linux(ubuntu). The problem is that if the application unexpectedly finishes(seg. fault or user kills it) the shared memory remains attached and no other process can create it again. Recall from QSharedMemory doc:
Unix: QSharedMemory "owns" the shared memory segment. When the last
thread or process that has an instance of QSharedMemory attached to a
particular shared memory segment detaches from the segment by
destroying its instance of QSharedMemory, the Unix kernel release the
shared memory segment. But if that last thread or process crashes
without running the QSharedMemory destructor, the shared memory
segment survives the crash.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Ensure single instanse of Cevirgec application
QSharedMemory shared(ApplicationConstants::
if( !shared.create( 512, QSharedMemory::ReadWrite) )
{
// QMessageBox msgBox;
QMessageBox::critical(0, QObject::tr("application is already running!"), QObject::tr("application is already running!"), QMessageBox::Ok, QMessageBox::Ok);
qCritical() << "application is already running!";
exit(0);
}
else {
qDebug() << "application staring...";
}
return a.exec();
}
What solutions can you suggest here? How can I assure that the shared memory is cleared(or whatever verb used generally) after the process eventually finishes. I need something like finally in java all around the main function :/
EDIT: (Solution)
I have achieved the desired behavior by using QSharedMemory and catching SIGSEGV signal then call sharedMemory.detach() in the signal handler.
You can catch the signals that crash your program and use a handler that calls the QSharedMemory destructor.
Truth is that if your program needs to be killed or has a segfault, then you cannot really do anything about it. Shared memory is not the best choice for ensuring single instance of appliction under UNIX/Linux. Try using semaphores instead, as they are getting closed as soon as your application terminates.
EDIT:
From documentation of sem_close
All open named semaphores are automatically closed on process
termination, or upon execve(2).
I also must add that ensuring single-app contraint might have weird consequences on system like linux - imagine somebody logged via ssh with X tunneling and trying to start your app - if somebody is already using it, it will not start. This will be rather confisunig. You are application developer and should know best if you need per-system per-user or even per-X-session blockade.
If you want to use per-user blockade, then solution might be to add hidden file in user home directory containing current pid. Next application will check for this file, and if it exists AND /proc/[pid]/exe link points to current binary, then return error.
You could always run a script after termination of your program to manually clear the shared memory, semaphores, etc. on your system (mine is a Mac Pro running 10.8). I have inserted a script I use for this when running programs that use QSharedMemory, and use it when the program quits unexpectedly and leaves the shared memory instances "hanging".
Keep in mind this will remove all shared memory instances associated with your user name. If you have multiple programs running and using shared memory instances, you should either wait until every program is done, or adjust the script as needed to only delete the shared memory instances that were created by your program.
#!/bin/bash
ME=$(whoami)
IPCS_S=$(ipcs -s | grep $ME | sed "s/ / /g" | cut -f2 -d " ")
IPCS_M=$(ipcs -m | grep $ME | sed "s/ / /g" | cut -f2 -d " ")
IPCS_Q=$(ipcs -q | grep $ME | sed "s/ / /g" | cut -f2 -d " ")
echo "Clearing Semaphores"
for id in $IPCS_S
do
ipcrm -s $id
done
echo "Clearing Shared Memory"
for id in $IPCS_M
do
ipcrm -m $id
done
echo "Clearing Message Queues"
for id in $IPCS_Q
do
ipcrm -q $id
done
Related
I have a C++ program which is called at startup via a cronjob (in crontab):
#reboot sudo /home/pi/CAN/RCR_datalogging/logfileControl
Which does run logfileControl anytime the Pi is booted as it shows up in the list of running programs (ps -e). LogfileControl contains two system calls to C++ programs related to SocketCAN (SocketCAN is part of the Linux Kernel, it allows for dealing with CAN data as network sockets). I want logfileControl to run on startup so that it can initialize the CAN socket (system call 1) and then start the first logfile (systemcall 2, candumpExternal, this is candump from socketCAN with a minor modification to make the logfile a specific location rather than just where candump is, but using the original version had the same issue). The first systemcall seems to be working properly as if I try and initialize the socket again it is busy, but the second systemcall doesn't appear to be happening as a logfile is not created at all as a logfile is not created. If I manually run logfileControl from the command line it works as expected and creates the logfile which has left me quite confused...
Does anyone have an insight as to what is going on here?
system("sudo /sbin/ip link set can0 up type can bitrate 500000");
// This is ran initially as logging should start as soon as the pi is on
system("/home/pi/CAN/RCR_datalogging/candumpExternal can0 -l -s 0"); // candump with the option to log(-l) as well as
// continue to output to console (-s 0)
std::cout <<"Setup Complete" << std:: endl;
while(true) { //sleeping indefinitely so that the program can stay open and wait for button presses
sleep(60);
}
Edit: I also tried adding a simple 5 second pause at the beginning of the program, but this didn't seem to make any difference.
When a Qt application that uses QSharedMemory crashes, some memory handles are left stuck in the system.
The "recommended" way to get rid of them is to
if(memory.attach(QSharedMemory::ReadWrite))
memory.detach();
bool created = memory.create(dataSize, QSharedMemory::ReadWrite);
In theory the above code should work like this:
We attach to a left over piece of sh...ared memory, detach from it, it detects that we are the last living user and gracefully goes down.
Except... that is not what happens in a lot of cases. What I actually see happening, a lot, is this:
// fails with memory.error() = SharedMemoryError::NotFound
memory.attach(QSharedMemory::ReadWrite);
// fails with "segment already exists" .. wait, what?! (see above)
bool created = memory.create(dataSize, QSharedMemory::ReadWrite);
The only somewhat working way I've found for me to work around this is to write a pid file on application startup containing the pid of the currently running app.
The next time the same app is run it picks up this file and does
//QProcess::make sure that PID is not reused by another app at the moment
//the output of the command below should be empty
ps -p $previouspid -o comm=
//QProcess::(runs this script, reads output)
ipcs -m -p | grep $user | grep $previouspid | sed "s/ / /g" | cut -f1 -d " "
//QProcess::(passes the result of the previous script to clean up stuff)
ipcrm -m $1
Now, I can see the problems with such approach myself, but it is the only thing that works
The question is: can someone explain to me what exactly is the deal with not so not existing memory in the first piece of code above and how to deal with it properly?
Some time ago I needed to write c++ code to kill some process. In my main program I run large CAE-system package with system("...") with different filename strings on input. CAE-software creates many processes, that contain in process name string filename). Some of the CAE-processes worktime > max_time, than I need to shut them down:
//filename contains part of CAE-process name
string s="/bin/kill -9 `ps aux | grep "+filename+" | awk {'print $2'}`";
system(s.c_str());
The output was:
Usage:
kill pid ... Send SIGTERM to every process listed.
kill signal pid ... Send a signal to every process listed.
kill -s signal pid ... Send a signal to every process listed.
kill -l List all signal names.
kill -L List all signal names in a nice table.
kill -l signal Convert between signal numbers and names.
I tried to run with execvp, tried different ways running kill or pkill over bash script, calling system("name_of_script.sh"), where script contained kill -9 *filename* but the result was the same.
Using kill and /bin/kill gave the same output, bash -c kill... too.
Using kill from my system (Ubuntu Natty) gnome-terminal:
kill -9 `ps aux | grep filename | awk {'print $2'}`
shutdown all necessary processes! It works.
When using pkill, as I could understand, we need full process name to kill it, but I have only part of name.
I also tried to wrap computational process into a child thread using pthreads and stop it with pthread_cancel, but it doesn't work because of CAE-system process doesn't receive signals (I think, trapping them), the only way is SIGTERM.
Killing child-thread-"wrap" with pthread_kill also kills the parent (my main program).
I don't know CAE-process pids to call kill from signals.h
Closing main program do not stop CAE-processes (and the do not have -Z flag, so are they aren't my program process childs??)
How can I close CAE-processes, that run > MAXTIME from my main program?
The problem was that I was running main program via debugger (gdb) in QtCreator. Without QtCreator shell-script runs with arguments the right way, though arguments are passed correctly both ways.
Also I have to clear some CAE processes, that don't have filename in cmdline, but that are parents or children of this process.
In shell-script you can use:
cat /proc/"$P"/status | grep PPid | grep -o "[0-9]*"
where $P is a variable with pid of killed process.
Here are several methods to kill all child processes.
I'll write smth. similar in C++ that will scan /proc/xxxx/status till PPid= ppid_of_my main_program and cut that branch.
You don't have to open a shell to kill a process. Just use the "kill" function:
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
http://linux.die.net/man/2/kill
To find a process to kill read the following directory:
/proc/####/cmdline
Where #### is the number of any running process id. So the code roughly would be to read the /proc directory and list out all the numerical directories, these are the current running processes, and you find the name of the command that spawned that process in the "cmdline" file in that directory. You can then use a regular expression, or a string comparison to identify processes to kill.
This should just work assuming filename isn't too much exotic or contains a regular expression pattern:
string s="pkill -9 -f "+filename";
system(s.c_str());
As a side note, -9 is a last resort signal, not something you should start with. I would thus recommend the less brutal:
string s="pkill -f "+filename"+";sleep 2; pkill -9 -f "+filename;
system(s.c_str());
I have to make a semaphore array for a C++ project. I'm not calling semget() from main(); I've got a separate method to make it easier, albeit a method in main.cpp. When my program reaches semget(semkey,nsems,0666|IPC_CREAT), it returns -1 with an EACCES errno, which apparently means "A semaphore identifier exists for key, but operation permission as specified by the low-order 9 bits of semflg would not be granted."
I've gone over and over my code with GDB. All three parameters for semget() look right, and this is the first point at which the program call semget(), so the semaphore doesn't exist already; I even ran ipcs -s to make sure. I've got #include <sys/sem.h> at the top of main.cpp.
What's going on here? I've already created and attached a shared memory segment, could that have something to do with it? I can't see how.
From the manual :
EACCES A semaphore set exists for key, but the calling process does not have permission to
access the set, and does not have the CAP_IPC_OWNER capability.
As a reminder, since semaphore are system object, it is deleted only when a system call is explicitly issued for this. (semctl with IPC_RMID, or ipcrm term command).
In addition, the semkey has to be unique (retrieve from a ftok() function for example), or it is possible that another program created it before your very first call to semget. Since, it would exist, you would catch the so-called EACCES error, cause not all programs uses 0666 permission on semaphore like you do.
Reboot flushes the shared objects pool (semaphore, shared memory segments, message queue) as would :
#!/bin/bash
for i in `ipcs -s | cut -f 2 -d ' '`
do
ipcrm -s $i
done
for i in `ipcs -m | cut -f 2 -d ' '`
do
ipcrm -m $i
done
for i in `ipcs -q | cut -f 2 -d ' '`
do
ipcrm -q $i
done
What is the best way to prevent a Linux program/daemon from being executed more than once at a given time?
The most common way is to create a PID file: define a location where the file will go (inside /var/run is common). On successful startup, you'll write your PID to this file. When deciding whether to start up, read the file and check to make sure that the referenced process doesn't exist (or if it does, that it's not an instance of your daemon: on Linux, you can look at /proc/$PID/exe). On shutdown, you may remove the file but it's not strictly necessary.
There are scripts to help you do this, you may find start-stop-daemon to be useful: it can use PID files or even just check globally for the existence of an executable. It's designed precisely for this task and was written to help people get it right.
Use the boost interprocess library to create a memory block that will be created by the process. If it already exists, it means that there is another instance of the process. Exit.
The more precise link to what you need would be this one.
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/scoped_ptr.hpp>
int main()
{
using boost::interprocess;
boost::scoped_ptr<shared_memory_object> createSharedMemoryOrDie;
try
{
createSharedMemoryOrDie.reset(
new shared_memory_object(create_only, "shared_memory", read_write));
} catch(...)
{
// executable is already running
return 1;
}
// do your thing here
}
If you have access to the code (i.e. are writing it):
create a temporary file, lock it, remove when done, return 1; if file exists, or,
list processes, return 1; if the process name is in the list
If you don't:
create a launcher wrapper to the program that does one of the above
I do not know what your exact requirement is but I had a similar requirement; in that case I started my daemon from a Shell script ( it was a HP-UX machine) and before starting the daemon I checked if an exec by same name is already running. If it is; then don't start a new one.
By this way I was also able control the number of instances of a process.
I think this scheme should work (and is also robust against crashes):
Precondition: There is a PID file for your application (typically in /var/run/)
1. Try to open the PID file
2. If it does not exist, create it and write your PID to it. Continue with the rest of the program
3. If it exist, read the PID
4. If the PID is still running and is an instance of your program, then exit
5. If the PID does not exist or is used by another program, remove the PID file and go to step 2.
6. At program termination, remove the PID file.
The loop in step 5 ensures that, if two instances are started at the same time, only one will be running in the end.
Have a pid file and on the startup do a 'kill -0 <pid>'. Where is the value read from file. If the response is != 0 then the daemon is not alive and you might restart it
Another approach would be to bind to a port and handle the bind exception on the second attempt to start the daemon. If the port is in use then exit otherwise continue running the daemon.
I believe my solution is the simplest:
(don't use it if racing condition is a possible scenario, but on any other case this is a simple and satisfying solution)
#include <sys/types.h>
#include <unistd.h>
#include <sstream>
void main()
{
// get this process pid
pid_t pid = getpid();
// compose a bash command that:
// check if another process with the same name as yours
// but with different pid is running
std::stringstream command;
command << "ps -eo pid,comm | grep <process name> | grep -v " << pid;
int isRuning = system(command.str().c_str());
if (isRuning == 0) {
cout << "Another process already running. exiting." << endl;
return 1;
}
return 0;
}