Getting the pid of my children using linux system calls in C++ - c++

I have a process that interfaces with a library that launches another process. Occasionally this process gets stuck and my program blocks in a call to the library. I would like to detect when this has happened (which I am doing currently), and send a kill signal to all these hung processes that are a child of me.
I know the commands to kill the processes, but I am having trouble getting the pids of my children. Does anyone know of a way to do this?

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *fp = popen("ps -C *YOUR PROGRAM NAME HERE* --format '%P %p'" , "r");
if (fp == NULL)
{
printf("ERROR!\n");
}
char parentID[256];
char processID[256];
while (fscanf(fp, "%s %s", parentID, processID) != EOF)
{
printf("PID: %s Parent: %s\n", processID, parentID);
// Check the parentID to see if it that of your process
}
pclose(fp);
return 1;
}

This question is very similar to one asked the other day. I would suggest taking a look here to see if the answers are satisfactory in your case. Basically you will probably have to read through /proc.

I don't think "ps" is the answer. You could iterate the process list yourself to look for your own process's children, but it's a much better idea to modify the library so it provides the PIDs when you launch them.
This library must be pretty lame. What kind of deal do you have with its vendor? Can you not get on to their support to fix it?

Related

In a C++ application in Mac or Windows, is there a way to determine if a given ProcessId still exists?

I have a QT application that runs on both Windows and Mac. Is there a way to provide a PID, and get back:
If the PID exists
The name of the process under that PID
For Windows I thing I can use EnumProcesses() to find out what I need, but how can this be done on Mac?
So it's a QT question. That constrains the space enough that I can provide an answer for the most reasonable case.
A good portable program probably does not monitor arbitrary processes but only its own; and for that everything is well in hand. Child processes are spawned using the QProcess class, and it provides of itself what you need in the form of the stateChanged signal. You don't ever ask if the process ID is good; you get told when it's no longer good.
If you insist on checking if the PID is good; you're in luck. If /proc/self exists but /proc/${pid} doesn't than the PID isn't good anymore. This works about as well as EnumProcesses on windows. You can get the process name from /proc/${pid}/exe (it's a symbolic link, so call readlink() on it). If /proc/self doesn't exist, you probably can't enum processes because the system is in a degenerate state.
#include <errno.h>
#include <libproc.h>
bool is_process_active_by_pid(pid_t pid , char * exe_path)
{
int ret;
char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
bool is_active;
ret = proc_pidpath (pid, pathbuf, sizeof(pathbuf));
if ( ret <= 0 ) {
fprintf(stderr, "PID %d: proc_pidpath ();\n", pid);
fprintf(stderr, " %s\n", strerror(errno));
is_active = false;
} else {
printf("proc %d: %s\n", pid, pathbuf);
is_active = true;
strcpy(exe_path , pathbuf);
}
return is_active;
}
On Windows:
If the PID exists
You can use OpenProcess() for it, giving it the desired PID. You have to do this anyway for the next step, so there is no point in wasting time using EnumProcesses() at all.
The name of the process under that PID
Once you have opened a HANDLE to the process, you can use GetModuleFileNameEx(), GetProcessImageFileName(), or QueryFullProcessImageName() to get the full path and filename to the process. If you want a more human-readable display name, you can pass that path+filename to GetFileVersionInfo() and VerQueryValue() to query its display name. Or, use the path+file with EnumServiceStatus() and QueryServiceConfig() to find a matching SCM service and get its display name.

Subprocess communication. C++

I'm trying to write a C++ program which will start new process (some script, programm, command) like daemon and gets some info from it (stdout). I'm trying to use popen(). But subprocess finishing when main program complete. I dont know, does C++ have something easy in use like Python (subprocessing). There is my code:
#include <stdio.h>
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
FILE *in;
char buff[512];
in = popen(argv[1], "r");
fgets(buff, sizeof(buff), in);
cout << buff;
}
P.S: & in the end of executive command doesn't helps.
fgets doesn't wait for the subprocess to complete, and neither does popen.
You need to read until the end of in:
while (fgets(buff, sizeof(buff), in))
{
cout << buff;
}
Reference for popen function: http://man7.org/linux/man-pages/man3/popen.3.html
Excerpt:
"The popen() function opens a process by creating a pipe, forking, and invoking the shell."
I think that because of the fork mechanism, when your (calling) process ends, its child process (the called one) is stopped too, at least as default behaviour.
One option is to keep reading from the pipe (and keep the caller process running) until the child process ends.
Your code is also missing a pclose(in) before exiting.
See also this other post on StackOverflow.
Have a look here https://github.com/arun11299/cpp-subprocess
This library can be exactly what you're looking for.

Open a few files, wait ~30 mins, relaunch them in C++

I posted a thread about how to do this in batch but it turns out batch scripting isn't very popular and I barely even know it so now I'm asking for your help doing this in C++.
here's what I tried
#include <Windows.h>
using namespace std;
void openBat(char* path) {
system(path);
}
int main() {
for(;;) {
openBat("C:\\Users\\Ivan\\Desktop\\folder\\run.bat");
Sleep(1800000);
//kill opened process
}
return 0;
}
I'm not sure how to kill the opened process because every time I run the bat script it will have a new ID and I can't kill by name because I need to have 4 of these open. All help is appreciated.
What you're doing there isn't really C++. You're basically using windows to interprete the commands you pass it like batch would do. Here is what you want to do in C++, even if it only runs on Windows.
#include <Windows.h>
#include <string>
std::wstring GetEnvString()
{
wchar_t* env = GetEnvironmentStrings();
std::wstring result{ env };
FreeEnvironmentStrings(env);
result.push_back('\0');
return result;
}
int main()
{
//Setup needed structures
STARTUPINFO si{ sizeof si };
PROCESS_INFORMATION pi;
//Command line (read- and writeable)
wchar_t cmd[] = L"cmd.exe /C C:\\Users\\Ivan\\Desktop\\folder\\run.bat";
//Create process
CreateProcess(nullptr, cmd, nullptr, nullptr, false, CREATE_UNICODE_ENVIRONMENT,
const_cast<wchar_t*>(GetEnvString().c_str()), nullptr, &si, &pi);
Sleep(1800000);
//Process Termination
TerminateProcess(pi.hProcess, 0);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
I'd recommend you read up on the CreateProcess function, as well as the Terminate Process one. There is also an example from Microsoft about how to use the former of the two. I hope this information can help you.
edit: Fixed stuff. Should work now. Credits to user4581301, his links were really useful.
I think the solution can be killing the self process tree without killing process itself.
Terminate a process tree (C for Windows)
When you create a process, hold onto the process handle and use the handle to terminate the when you are done. With the handle you know exactly which of possibly thousands of instances of the same process you want dead.
Note: Terminating a process may have undesirable results. You are almost always better off writing the processes in such a way that you can message them and request that they terminate themselves politely. How you would do this with a batch file... Smurfed if I know. Someone else may have a waaaaay better answer to this problem, and I'm fine with that. One day I might need that better solution.
On Windows you likely want CreateProcess and TerminateProcess.
Running a batchfile with CreateProcess is covered here: Use CreateProcess to Run a Batch File
Terminating a process launched with Create process is covered here:
how to terminate a process created by CreateProcess()?

Returning output from bash script to calling C++ function

I am writing a baby program for practice. What I am trying to accomplish is basically a simple little GUI which displays services (for Linux); with buttons to start, stop, enable, and disable services (Much like the msconfig application "Services" tab in Windows). I am using C++ with Qt Creator on Fedora 21.
I want to create the GUI with C++, and populating the GUI with the list of services by calling bash scripts, and calling bash scripts on button clicks to do the appropriate action (enable, disable, etc.)
But when the C++ GUI calls the bash script (using system("path/to/script.sh")) the return value is only for exit success. How do I receive the output of the script itself, so that I can in turn use it to display on the GUI?
For conceptual example: if I were trying to display the output of (systemctl --type service | cut -d " " -f 1) into a GUI I have created in C++, how would I go about doing that? Is this even the correct way to do what I am trying to accomplish? If not,
What is the right way? and
Is there still a way to do it using my current method?
I have looked for a solution to this problem but I can't find information on how to return values from Bash to C++, only how to call Bash scripts from C++.
We're going to take advantage of the popen function, here.
std::string exec(char* cmd) {
FILE* pipe = popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
pclose(pipe);
return result;
}
This function takes a command as an argument, and returns the output as a string.
NOTE: this will not capture stderr! A quick and easy workaround is to redirect stderr to stdout, with 2>&1 at the end of your command.
Here is documentation on popen. Happy coding :)
You have to run the commands using popen instead of system and then loop through the returned file pointer.
Here is a simple example for the command ls -l
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *process;
char buff[1024];
process = popen("ls -l", "r");
if (process != NULL) {
while (!feof(process)) {
fgets(buff, sizeof(buff), process);
printf("%s", buff);
}
pclose(process);
}
return 0;
}
The long approach - which gives you complete control of stdin, stdout, and stderr of the child process, at the cost of fairly significant complexity - involves using fork and execve directly.
Before forking, set up your endpoints for communication - pipe works well, or socketpair. I'll assume you've invoked something like below:
int childStdin[2], childStdout[2], childStderr[2];
pipe(childStdin);
pipe(childStdout);
pipe(childStderr);
After fork, in child process before execve:
dup2(childStdin[0], 0); // childStdin read end to fd 0 (stdin)
dup2(childStdout[1], 1); // childStdout write end to fd 1 (stdout)
dup2(childStderr[1], 2); // childStderr write end to fd 2 (stderr)
.. then close all of childStdin, childStdout, and childStderr.
After fork, in parent process:
close(childStdin[0]); // parent cannot read from stdin
close(childStdout[1]); // parent cannot write to stdout/stderr
close(childStderr[1]);
Now, your parent process has complete control of the std i/o of the child process - and must safely multiplex childStdin[1], childStdout[0], and childStderr[0], while also monitoring for SIGCLD and eventually using a wait-series call to check the process termination code. pselect is particularly good for dealing with SIGCLD while dealing with std i/o asynchronously. See also select or poll of course.
If you want to merge the child's stdout and stderr, just dup2(childStdout[1], 2) and get rid of childStderr entirely.
The man pages should fill in the blanks from here. So that's the hard way, should you need it.

How to call execute command line in C++

For example, I have a script ./helloworld.sh
I would like to call it in C++, how do I do that? Which library can be used?
try
system("./helloworld.sh");
If you just want to run it (and nothing else)
system("./helloworld.sh");
If you need to get the stdin/stdout then you need to use popen()
FILE* f = popen("./helloworld.sh","r");
try system().
In C there are also the execxxx functions from unistd.h. They have a big advantage over the simple system as you can specify environment variables for your process to run in among other levels of control for the arguments management.
There are at least two possible ways.
(I suppose you are asking about Unix-like systems when using shell scripts).
The first one is very simple, but is blocking (it returns after the command has been completed):
/* Example in pure C++ */
#include <cstdlib>
int ret = std::system("/home/<user>/helloworld.sh");
/* Example in C/C++ */
#include <stdlib.h>
int ret = system("/home/<user>/helloworld.sh");
The second way is not that easy, but could be non-blocking (script can be run as parallel process):
/* Example in C/C++ */
#include <unistd.h>
pid_t fork(void);
int execv(const char *path, char *const argv[]);
/* You have to fork process first. Search for it, if you don't know how to do it.
* In child process you have to execute shell (eg. /bin/sh) with one of these
* exec* functions and you have to pass path-to-your-script as the argument.
* If you want to get script output (stdout) on-the-fly, you can do that with
* pipes. Just create the reading pipe in parent process before forking
* the process and redirect stdout to the writing pipe in the child process.
* Then you can just use read() function to read the output whenever you want.
*/
if you also want to get the output of the script do
char fbuf[256];
char ret[2555];
FILE *fh;
if ((fh = popen("./helloworld.sh", "r")) == NULL) {
return 0;
}else{
while ( fgets(fbuf, sizeof(fbuf), fh) ) {
strcat(ret, fbuf);
}
}
pclose(fh);