So, what exactly is the deal with QSharedMemory on application crash? - c++

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?

Related

Wine check if WINEPREFIX is active(desktop=a/desktop=b/etc.) using c++

I have a c++ program I'm writing that uses wine to run Diablo II using the system() function calling a wine command.
(system("wine explorer /desktop=a,800x600 ~/Diablo/Diablo.exe"))
I have if/else statements runnning that command (as a condition) with /desktop=a, desktop=b, etc. in order to have multiple diablo windows running at the same time but my program is calling each one in order(all the way to desktop=g before exiting, so it's kind of annoying).
my question is: How can I test (I'm assuming with a wine argument) to see if desktop=a is active and if it's not run diablo in it, but if it is then move on to test desktop=b?
edit: This is what I have so far(goes up to desktop=g)
int main()
{
if (system("wine explorer /desktop=a,800x600 ~/Diablo/Diablo.exe"))
{
}
else if (system("wine explorer /desktop=b,800x600 ~/Diablo/Diablo.exe"))
{
}
edit 2: After some more research I did find this (bash):
result=`ps -Al | grep Game.exe | wc -l` && echo $result
that should work for my problem but I can't figure out how to call it from c++ in a way that allows me to pipe the output from it to a variable (not without creating a file and reading from that wich I'd like to try to avoid if possible).

fetching a http process user using bash

Whats the best way to fetch a web process user (apache|nginx|www-data) for bash script usage?
In my case for setting up folder permissions and changing to the poper owner.
Currently I'm using:
ps aux | grep -E "(www-data|apache|nginx).*(httpd|apache2|nginx)" \
| grep -o "^[a-z\-]*" | head -n1
inside a bash script to fetch the owner of the http process.
Any hints on a more smartly solution or a better regex whould be great.
Your solution will really depend on your operating system. One option might be to check whether likely candidates exist in your password file:
user=$(awk -F: '/www|http/{print $1;exit}' /etc/passwd)
If you really want to look for the owner of running processes, remember that Apache often launches a root-owned "master" process, then launches children as the web user. So perhaps something like this:
user=$(ps aux|awk '$1=="root"{next} /www|http|apache/{print $1;exit}')
But you should also be able to determine things based on OS detection, since things tend to follow standards:
case "`uname -s`" in
Darwin) user=_www; uid=70 ;;
FreeBSD) user=www; uid=80 ;;
Linux)
if grep Ubuntu /etc/lsb-release; then
user=www-data; uid=$(id -u www-data)
elif [ -f /etc/debian_version ]; then
user=www-data; uid=$(id -u www-data)
elif etc
etc
fi
;;
esac
I'm not up on the best ways to detect different Linux distros, so that may require a bit of additional research for you.

Permissions issue calling bash script from c++ code that apache is running

The goal of this code is to create a stack trace whenever a sigterm/sigint/sigsegv/etc is caught. In order to not rely on memory management inside of the C++ code in the case of a sigsegv, I have decided to write a bash script that will receive the PID and memory addresses in the trace array.
The Sig events are being caught.
Below is where I generate the call to the bash script
trace_size = backtrace(trace, 16);
trace[1] = (void *)ctx->rsi;
messages = backtrace_symbols(trace, trace_size);
char syscom[356] = {0};
sprintf(syscom,"bash_crash_supp.sh %d", getpid());
for (i=1; i<(trace_size-1) && i < 10; ++i)
{
sprintf(syscom,"%s %p",syscom,trace[i]);
}
Below is where my issue arises. The command in syscom is generating correctly. I can stop the code before the following popen, run the command in a terminal, and it functions correctly.
However running the script directly from the c++ code does not seem to work.
setuid(0);
FILE *bashCommand = popen(syscom,"r");
char buf[256] = {0};
while(fgets(buf,sizeof(buf),bashCommand) != 0) {
LogMessage(LOG_WARNING, "%s\n", buf);
}
pclose(bashCommand);
exit(sig);
The purpose of the bash script is to get the offset from /proc/pid/maps, and then use that to run addr2line to get the file name/line number.
strResult=$(sudo cat /proc/"$1"/maps | grep "target_file" | grep -m 1 '[0-9a-fA-F]')
offset=$( cut -d '-' -f 1 <<< "$strResult");
However offset is getting 0 when I run from the c++ code, but when I run the exact same command (that is stored in syscom in the c++ code) in a terminal, I get the expected output.
I have been trying to fix this for a while. Permissions are most likely the issue, but I've tried to work around these with every way I know of/have seen via google. The user trying to run the script (currently running the c++ code) is apache.
The fix does not need to worry about the security of the box. If something as simple as "chmod 777 /proc -r" worked, that would have been the solution (sadly the OS doesn't let me mess do such commands with /proc).
Things I've already tried:
Adding `` around the command that's stored in syscom from the c++ code
chown the script to apache
chmod 4755 on the bash_crash_supp.sh script, allowing it to always fire as root.
I have added apache to sudoers (visudo), allowing them to run sudo without using a password
I have added a sub file to sudoers.d (just in case) that does the same as above
I have looked into objdump, however it does not give me either the offset or the file/line num for an addr (from what I can see)
I have setuid(0) in the c++ code to set the current user to root
Command generated in C++
bash_crash_supp.sh 25817 0x7f4bfe600ec8 0x7f4bf28f7400 0x7f4bf28f83c6 0x7f4bf2904f02 0x7f4bfdf0fbb0 0x7f4bfdf1346e 0x7f4bfdf1eb30 0x7f4bfdf1b9a8 0x7f4bfdf176b8
Params in bash:
25817 0x7f4bfe600ec8 0x7f4bf28f7400 0x7f4bf28f83c6 0x7f4bf2904f02 0x7f4bfdf0fbb0 0x7f4bfdf1346e 0x7f4bfdf1eb30 0x7f4bfdf1b9a8 0x7f4bfdf176b8
Can anyone think of any other ways to solve this?
Long story short, almost all Unix-based systems ignore setuid on any interpreted script (anything with a shebang #!) as a security precaution.
You may use setuid on actual executables, but not the shell scripts themselves. If you're willing to take a massive security risk, you can make a wrapper executable to run the shell script and give the executable setuid.
For more information, see this question on the Unix StackExchange: https://unix.stackexchange.com/a/2910

How to kill process in c++, knowing only part of its name

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());

C++ shared memory leak, how to clear shared memory?

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