Launching a program using C++ code

Schadenfroh

Elite Member
Mar 8, 2003
38,416
4
0
Hey,

I am trying to launch an external program to capture its (debug) output to a textfile.

What I have tried is assigning it to a thread and then trying to kill the thread, but it does not kill the application. For example (having omitted the program that I am intending to run and just using gedit with no debug output capturing):

Prototype / imports:
#include <pthread.h>
#include <sys/signal.h>
void *executeApp(void *);

code to create child thread and then kill it after a delay:
pthread_t cTid;
pthread_create(&cTid, NULL, executeApp, NULL);
sleep(5);
pthread_kill(cTid, SIGALRM);

the process's function:
void *executeApp(void *){
int returnValue = system("gedit");
}

Any thoughts on how I can launch an external program on another thread, let it execute for a shortwhile, then kill that thread with the parent thread other than this (since gedit in this case remains open)?

Thanks
 

Crusty

Lifer
Sep 30, 2001
12,684
2
81
Threading on linux is definitely not my strong point, but I'm guessing that your thread is creating a new process for gedit so when you go to kill the thread, you are only killing the worker thread not the actual gedit process. So you would need to get the PID for your new process and kill that, and then stop your thread.
 

Schadenfroh

Elite Member
Mar 8, 2003
38,416
4
0
Originally posted by: Crusty
You would need to get the PID for your new process and kill that, and then stop your thread.

Would this best be accomplished by getting the list of processes on the system before the system("*"); command in the child thread and then comparing that list to the post execution process list and killing all processes spawned in the meantime?

In other words, how would the child thread be able to acquire the process id of the application that it launched using the system("") command?

Thanks for the quick reply!
 

Crusty

Lifer
Sep 30, 2001
12,684
2
81
I'm sure someone else will know the best way, but most applications have a way for you to specify a pid file to store the pid when you start the process. So if you can set that, then you can just read that file in to get the PID.

edit:

So when you start a process with a & you get the pid output via stdout.

So like gedit& spits out [1] 12345 where 12345 is the pid

So with some basic stream redirection you can spit that pid right into a text file.
 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
13
81
www.markbetz.net
Every time I have seen this come up the recommendation has been to use fork(), which returns a pid you can then use to kill the process on request.
 

Crusty

Lifer
Sep 30, 2001
12,684
2
81
Originally posted by: Markbnj
Every time I have seen this come up the recommendation has been to use fork(), which returns a pid you can then use to kill the process on request.

Ah yes. Much easier then trying to store the PID in a file
 

Schadenfroh

Elite Member
Mar 8, 2003
38,416
4
0
Originally posted by: Markbnj
Every time I have seen this come up the recommendation has been to use fork(), which returns a pid you can then use to kill the process on request.

The program that I am launching the programs from is fairly sizable, I was trying to use threads to reduce overhead.

Would the program launched by the system("*"); command using a child process be terminated along with the child process if terminated by the parent process?
 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
13
81
www.markbetz.net
Originally posted by: Schadenfroh
Originally posted by: Markbnj
Every time I have seen this come up the recommendation has been to use fork(), which returns a pid you can then use to kill the process on request.

The program that I am launching the programs from is fairly sizable, I was trying to use threads to reduce overhead.

Would the program launched by the system("*"); command using a child process be terminated along with the child process if terminated by the parent process?

I guess I am a little unclear on the goal, and I'm no Linux expert. But I don't think you can get a separate executable image running without starting a new process. You can point a thread at a function within your process, but to get another image loaded and running you need to create a new process. Otherwise you'd be loading an external executable image into your process address space, which has some interesting implications.
 

tfinch2

Lifer
Feb 3, 2004
22,114
1
0
If you don't want to use fork (but I recommend you do), you can use the pidof command to query the pid of a process by name to kill it. You can also use killall to kill a process by name. I really don't recommend these methods because you might have a multiple instances of the same process and you might not want to kill all of them.

The reason your new process doesn't die when you kill the thread is because creating a new thread does not create a new parent. The child process lives on because the parent is still alive (the main thread of your process).

EDIT: Also, if you were to kill the parent, the child process would not die either. IIRC, all orphaned processes are inherited by the init process regardless of how their parent terminates.

In other words, just use fork to get the PID, and kill to get rid of it when you are done.
 

Schadenfroh

Elite Member
Mar 8, 2003
38,416
4
0
I don't think you can get a separate executable image running without starting a new process
I realize this, but I did not want to fork my original program and then use the child process to launch the new program (thus having three processes).

Originally posted by: tfinch2
The reason your new process doesn't die when you kill the thread is because creating a new thread does not create a new parent. The child process lives on because the parent is still alive (the main thread of your process).

That makes sense, thanks for explaining that to me. I guess I will use fork.
 

hans007

Lifer
Feb 1, 2000
20,212
17
81
um...

maybe its different in linux, but if you are launching a seperate process i'm pretty sure that gets its own proces space. sure a process can have child threads, but can they have a child process?

in windows you would force terminate a process handle, which you can get from its pid . i'm sure at some level its pretty similar in linux.


i figure, when you run whatever it is in linux to start the process that call executes. i dont know exactly what that call sis but on windows its createprocess.


so that doesnt like block forever, it just runs and does it, and then if thats the only thing in your thread, the thread would get to the end , and the thread would shut off.

so running a thread, that launches a process, killing the thread (even if you say put a wait loop in it) would not shut off the process unless you coded a mechanism in to it to do that.
 

Schadenfroh

Elite Member
Mar 8, 2003
38,416
4
0
After digging through my textbook from last semester and digging around through the documentation of some of the libraries, I think I have it working the way that I want it to work. Here is what I did and it "appears" to work (launches the program and allows it to execute and then kills it after 5 sec.).

Libraries:
#include <sys/signal.h>
#include <sys/shm.h>
#include <sys/stat.h>

Function:
int segment_id;
pid_t* sharedMem;
const int size = 4096;

segment_id = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
sharedMem = (pid_t *) shmat(segment_id, NULL, 0);


pid_t cTid;


cTid = fork();

if (cTid < 0){
cerr << "Forking failed in analyzeApp" << endl;
} else if (cTid == 0){ //child process
*sharedMem = getpid(); //stores the spawned process' id into the shared variable
execvp("/home/schadenfroh/NetBeansProjects/PE_Analyzer/Test3.exe", NULL); //launches the application

} else{ //parent process
sleep(5); //waits for 5 sec.
kill((*sharedMem),SIGTERM); //kills the child process

}
 

hans007

Lifer
Feb 1, 2000
20,212
17
81
Originally posted by: Schadenfroh
After digging through my textbook from last semester and digging around through the documentation of some of the libraries, I think I have it working the way that I want it to work. Here is what I did and it "appears" to work (launches the program and allows it to execute and then kills it after 5 sec.).

Libraries:
#include <sys/signal.h>
#include <sys/shm.h>
#include <sys/stat.h>

Function:
int segment_id;
pid_t* sharedMem;
const int size = 4096;

segment_id = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
sharedMem = (pid_t *) shmat(segment_id, NULL, 0);


pid_t cTid;


cTid = fork();

if (cTid < 0){
cerr << "Forking failed in analyzeApp" << endl;
} else if (cTid == 0){ //child process
*sharedMem = getpid(); //stores the spawned process' id into the shared variable
execvp("/home/schadenfroh/NetBeansProjects/PE_Analyzer/Test3.exe", NULL); //launches the application

} else{ //parent process
sleep(5); //waits for 5 sec.
kill((*sharedMem),SIGTERM); //kills the child process

}




that seems like the wrong way to do it.



fork returns 0 if you are the child, or the pid if you are the parent. so why do the shared data and such, to get the pid, when the parent already has it

in your code above you already have the pid in cTid.... so why are you sharing memory you can just go

else{ //parent process
sleep(5); //waits for 5 sec.
kill((cTid),SIGTERM); //kills the child process

instead of sharing memory and having to deal with possible race conditions on your now un mutexed shared memory.


also this doesnt really "launch a process" it launches a copy of your current process not a different process.


 

Schadenfroh

Elite Member
Mar 8, 2003
38,416
4
0
Originally posted by: hans007
you can just go

You are correct, that does work and eliminates the need for the shared variable. I assumed incorrectly about the pid that fork returned.
 

Cerebus451

Golden Member
Nov 30, 2000
1,425
0
76
Not sure what is going on with your original thread creation, but I dug through some old code I had that needed to do something similar. I couldn't use fork because the main program was large and I didn't need to create another copy of it just to launch another process. The attached code is the basics of what I use. The main program creates a worker thread, which runs the command (which itself creates another thread for the program to run in). The worker thread waits for either the command to finish, or for the main program to tell it to terminate early. The extra sleep I have in the main program is just there to make sure that the gedit command is exiting from the thread cancel, and not from the main program terminating.

The worker thread I have doesn't do a whole lot. In the program this code was pulled from the worker threads are doing a lot more, possibly running several commands before exiting, just wanted to create something basic to show how it works.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>

#define TERMINATED -1
#define SUCCESS 0

typedef struct
{
char * cmd;
char active;
int retCode;
} COMMAND_STRUCT;

static void * ExecuteCommand (void * lpParameter)
{
int old;
COMMAND_STRUCT * ptr = (COMMAND_STRUCT *) lpParameter;

pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
ptr->retCode = system (ptr->cmd);
ptr->active = 0;

return 0;
}

extern char RunCommand (char * cmd,
char * threadTerm,
int * retCode)
{
pthread_t thread;
COMMAND_STRUCT parm;

parm.cmd = cmd;
parm.active = 1;
pthread_create (&thread,
NULL,
ExecuteCommand,
&parm);

while (parm.active)
{
if (*threadTerm)
{
pthread_cancel (thread);
parm.active = 0;
}
sleep (2);
}
*retCode = parm.retCode;
if (*threadTerm)
{
return TERMINATED;
}
else
{
return SUCCESS;
}
}

static void * workerThread (void * lpParameter)
{
int ret;
RunCommand ("gedit", lpParameter, &ret);
}

int main ()
{
pthread_t thread;
char term = 0;
pthread_create (&thread, NULL, workerThread, &term);
sleep(5);
term = 1;
sleep(5);
}
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
It sounds to me like you want to take Markbnj's advice and use fork() (or vfork()), followed by some form of exec() (e.g., execlp). Then you have exactly two processes... no superflous threads or anything. You can also try popen() if you want to redirect output to a file.

Threading, system(), etc aren't quite what you need.
 

Schadenfroh

Elite Member
Mar 8, 2003
38,416
4
0
Thanks guys, one last question. I have yet to see any guides to redirecting the debug console output (in order to capture the text). Almost everyone says to use this console argument to redirect it to a file. But, they do not seem to work with the exec() commands. Any idea how to capture a large amount of text from the debug console output of a program launched by the exec command since "myprogram 2> output.txt" is not an option?
 

KCfromNC

Senior member
Mar 17, 2007
208
0
76
Since you're not running the child via a shell, you won't be able to use the command line redirection stuff that shells provide. You'll need to duplicate what the shells are doing in your own program - look into pipe() and dup()/dup2(). Numerous examples are easy to find via google.
 
sale-70-410-exam    | Exam-200-125-pdf    | we-sale-70-410-exam    | hot-sale-70-410-exam    | Latest-exam-700-603-Dumps    | Dumps-98-363-exams-date    | Certs-200-125-date    | Dumps-300-075-exams-date    | hot-sale-book-C8010-726-book    | Hot-Sale-200-310-Exam    | Exam-Description-200-310-dumps?    | hot-sale-book-200-125-book    | Latest-Updated-300-209-Exam    | Dumps-210-260-exams-date    | Download-200-125-Exam-PDF    | Exam-Description-300-101-dumps    | Certs-300-101-date    | Hot-Sale-300-075-Exam    | Latest-exam-200-125-Dumps    | Exam-Description-200-125-dumps    | Latest-Updated-300-075-Exam    | hot-sale-book-210-260-book    | Dumps-200-901-exams-date    | Certs-200-901-date    | Latest-exam-1Z0-062-Dumps    | Hot-Sale-1Z0-062-Exam    | Certs-CSSLP-date    | 100%-Pass-70-383-Exams    | Latest-JN0-360-real-exam-questions    | 100%-Pass-4A0-100-Real-Exam-Questions    | Dumps-300-135-exams-date    | Passed-200-105-Tech-Exams    | Latest-Updated-200-310-Exam    | Download-300-070-Exam-PDF    | Hot-Sale-JN0-360-Exam    | 100%-Pass-JN0-360-Exams    | 100%-Pass-JN0-360-Real-Exam-Questions    | Dumps-JN0-360-exams-date    | Exam-Description-1Z0-876-dumps    | Latest-exam-1Z0-876-Dumps    | Dumps-HPE0-Y53-exams-date    | 2017-Latest-HPE0-Y53-Exam    | 100%-Pass-HPE0-Y53-Real-Exam-Questions    | Pass-4A0-100-Exam    | Latest-4A0-100-Questions    | Dumps-98-365-exams-date    | 2017-Latest-98-365-Exam    | 100%-Pass-VCS-254-Exams    | 2017-Latest-VCS-273-Exam    | Dumps-200-355-exams-date    | 2017-Latest-300-320-Exam    | Pass-300-101-Exam    | 100%-Pass-300-115-Exams    |
http://www.portvapes.co.uk/    | http://www.portvapes.co.uk/    |