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

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

Related

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

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?

Getting the actual process id of a command that is executed in background using C++

Lets say i have run a simple background process which is:
sleep 25 &
I execute it on the command line as :
> sleep 25 &
[1] 26390
> ps
PID TTY TIME CMD
26390 pts/52 0:00 sleep
6746 pts/52 0:02 tcsh
26391 pts/52 0:00 ps
>
You can see that sleep is executing in the background with pid 26390
Now I try to do the same thing using c++.there are many different system calls to do it btw.
using system
using fork
using pipe
I tried below code:
if(p=fork()){
//Main process
cout<<p<<endl;
}
else{
execv("sleep 20 &",(char **)NULL);
}
}
output is:
> ./a.out
27391
> ps
PID TTY TIME CMD
6746 pts/52 0:02 tcsh
27392 pts/52 0:00 ps
>
You can see that there is no sleep running in the background.
Now i tried another way:
FILE* pipe = popen("sleep 20 &", "r");
if(pipe){
char buffer[128];
while(fgets(buffer, 128, pipe));
cout<<buffer<<endl;
pclose(pipe);
}
This hangs for 20 seconds and i will never get that cout printed with the process id.
> ./a.out
>
Again I tried another way:
if(p=fork()){
//Main process
cout<<p<<endl;
}
else{
system("sleep 20 &");
}
}
> ./a.out
27464
> ps
PID TTY TIME CMD
27466 pts/52 0:00 sleep
27467 pts/52 0:00 ps
6746 pts/52 0:02 tcsh
Now you can see sleep running in the background but with different PID.
But what i need is the actual pid of the sleep command that is executed in the background.
I strongly believe that there should be some way to get the exact pid of the process running in the background in c++. Could anybody please help?
The process ID you are printing out is correct. The problem is that your sleep is not starting correctly.
There is no need to have a '&' in the arguments to sleep; your code is doing that already. If you do have the '&' the sleep is likely to complain because '&' is not a duration.
Try an exec call like this instead:
execlp("sleep", "sleep", "20", 0);
This searches the directories in PATH for a file called 'sleep', and replaces the current process with that process invoked with the arguments 'sleep' and '20'. These arguments are passed to main() using argv and argc.
Read the man page for exec for more details.
The exec family of functions do not take shell commands, and they don't start shells. Instead they replace the process with one loaded from disk. The way you use the execv function it will fail.
The system function, on the other hand, actually starts a shell for the command(s) to run in.
The way to get the pid of a process is very simple: Use the getpid function. As in
std::cout << "pid = " << getpid() << '\n';
If you fork and use the above before a proper call to an exec function will show the pid of the process that sleeps. But not if you call system or popen, because those functions fork new processes themselves. Talking about system, if you put it in its own process, then you don't need to use & to run in the background, the child process itself makes sure the command is already in the background.
Read C shell considered harmful, then switch to a nice interactive shell (like zsh, fish, bash). For scripting, consider Posix sh (or use real scripting languages).
Read Advanced Linux Programming (most of it is valuable for other Unix systems, including Solaris).
You should learn how to use fork(2), getpid(2), execve(2), pipe(2), waitpid(2) etc... (these are standardized by POSIX). We can't take hours to teach you that, but you definitely should read books about them. Understanding how fork works is tricky.
You may want to call sleep(3) function or nanosleep(2) syscall. You should not use system or popen to sleep (both will fork a shell process, which is useless in that case), just call the function!
Don't forget that stdio(3) is buffered. You probably need to call fflush(3) (in C), or std::flush in C++, wisely (in particular before fork).
As others pointed out, the PID you showed for the sleep command is the PID of the sleep command itself (i.e. what you said you needed). So the PID you printed out from the process is 27464, and the PID of the sleep you created with system() is 27466. Perhaps if you say more about what you're trying to do we can be of more help.

Use QProcess to only zcat as many lines as needed?

In Linux if I run this command
zcat bigFile | head
Then zcat will not decompress all of bigFile, only as much as it needs to in order to supply head with the data it needs.
But what about this
QProcess *process = new QProcess(this);
process->start("zcat bigFile");
process->readLine();
QTimer::singleShot(10000, process, SLOT(terminate()));
Will the zcat command that is run in process only decompress whatever is needed for readLine()? Or will it continuously zcat bigFile for 10 seconds?
Is it possible to use a QProcess similarly to the Linux pipe |, and thus only zcat as many lines as have been requested?
Will the zcat command that is run in process only decompress whatever
is needed for readLine()?
No
Or will it continuously zcat bigFile for 10 seconds?
Yes
To verify this, I wrote the following code
QProcess *process = new QProcess(this);
process->start("yes");
connect(process, SIGNAL(finished(int)), this, SLOT(_end()));
connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(_end()));
QByteArray byteArray = process->readLine(5);
QString line = QString(byteArray);
process->closeReadChannel(QProcess::StandardOutput);
QTimer::singleShot(5000, process, SLOT(terminate()));
This basically starts the yes command which continuously outputs this
y
y
y
y
... (and so on)
And then reads only one line from the output of yes, and then terminates the process 5 seconds later.
I ran this command while watching top, and the result is 5 seconds of yes taking 100% CPU, after which it quits. This clearly shows that yes does not merely print out one line and then halt or quit.
Even closing the stdout read channel (which ignores the rest of the output of yes) still doesn't pause the yes execution.
You could try pausing the QProcess periodically until you have enough time to process the buffer, but that could get messy.
When you call start() on QProcess, it executes the zcat program, as it does in a terminal. This is a separate process from your Qt program, so it's free to run independently from your Qt application, or in the case of the code you've provided, it will run until it is terminated 10 seconds later.
Whether or not you choose for your application to read the output from zcat is up to you, but it will still continue to run.
Also note that calling process->readline() straight afterwards is probably not the best way of handling the process as your program may try to read the output stream before any data is ready. Instead, you should either call waitForReadyRead() before readline(), or connect a slot to readyRead() signal of QProcess and call readline from that slot.
---- EDITED -----
Based on the change to the question: -
I think you're missing the point of the pipe command. As I understand it, all of the file will be decompressed by zcat, but its output is redirected to the head command. The head command only displays the first number of lines of a file, which is why you only see the first part.
This is like having a file test.txt and calling the command: -
cat test.txt | head
The whole file exists, but head will only display the first number of lines.

started from command line?

I have a simple C/CPP process running on a linux system. This is a.out.
Another process is capable to start a.out inside its code. This is b.out.
What code do I need inside a.out to understand that it is executed from the command line?
Eg ./a.out
Is there a way a process to know if it started from the cmd or started from another process?
You can't find out in general whether a program was started "from the command line" (by a user's explicit command), but you can find out whether its standard input and output are talking to a terminal/command window:
#include <unistd.h>
isatty(fileno(stdin))
and stdout return whether standard input/standard output are terminals.
If you need to know what process starting your program, use the getppid system call to get the parent's process ID (ppid), then read the pseudo-file /proc/ppid/cmdline.
You can check its parent task ID, using getppid()
You can do multiple things, but none will be 100% reliable:
isatty(0) to check whether standard input is a TTY terminal,
check for the parent task ID (getppid()), then lookup the parent's PID to match it against its executable's path (using whatever you want. a call to ps and some parsing could do, or have fun using /proc/)
you could also just have a look at the environment variables set up. do a printout of all the values contained in the env. To do that, either use the extern environ variable:
extern char **environ;
or modify your main() prototype to be:
int main(int ac, char **av, char **environ)
I would set an environment variable, in the parent process, to some value (say the parent pid), and have the child process check for it.
It is unlikely that a shell user would set this variable (call it something unlikely to name-clash), so if this variable is set to the expected value, then you know that it is being started from the parent process.
You can check whether its standard input is a terminal:
if(isatty(0)) { ... }
In short: you can't doing it directly.
In long: look you can check the getppid() value and compare it with the bash PID orb.out PID
TO search for a process inside the process table with Known PID with C you can do this:
1) get the PPID of a.out and search with this value in /porc and then if you find the folder check the cmdline file and check if this process is b.out or shell process.
2) you can deal with sysctl system call and dealing with kernel param's(you can google it)
3)
pid_t ppid = getppid();
system("pidof bash > text.in");
the system will get the pid of any shell process and write the result to text.in file
it contains all bash PID's space separated you can compare this values with getppid() value.
Good Luck.

How to get forkpty/execvp() to properly handle redirection and other bash-isms?

I've got a GUI C++ program that takes a shell command from the user, calls forkpty() and execvp() to execute that command in a child process, while the parent (GUI) process reads the child process's stdout/stderr output and displays it in the GUI.
This all works nicely (under Linux and MacOS/X). For example, if the user enters "ls -l /foo", the GUI will display the contents of the /foo folder.
However, bash niceties like output redirection aren't handled. For example, if the user enters "echo bar > /foo/bar.txt", the child process will output the text "bar > /foo/bar.txt", instead of writing the text "bar" to the file "/foo/bar.txt".
Presumably this is because execvp() is running the executable command "echo" directly, instead of running /bin/bash and handing it the user's command to massage/preprocess.
My question is, what is the correct child process invocation to use, in order to make the system behave exactly as if the user had typed in his string at the bash prompt? I tried wrapping the user's command with a /bin/bash invocation, like this: /bin/bash -c the_string_the_user_entered, but that didn't seem to work. Any hints?
ps Just calling system() isn't a good option, since it would cause my GUI to block until the child process exits, and some child processes may not exit for a long time (if ever!)
If you want the shell to do the I/O redirection, you need to invoke the shell so it does the I/O redirection.
char *args[4];
args[0] = "bash";
args[1] = "-c";
args[2] = ...string containing command line with I/O redirection...;
args[4] = 0;
execv("/bin/bash", args);
Note the change from execvp() to execv(); you know where the shell is - at least, I gave it an absolute path - so the path-search is not relevant any more.