I want to read the exit value from my console application to exit all the related threads with that application before exit.
This work for me on Windows try it
#include <csignal>
#include <iostream>
#include <ostream>
#include <string>
using namespace std;
namespace
{
volatile sig_atomic_t exit;
void signal_handler(int sig)
{
signal(sig, signal_handler);
exit= 1;
}
}
int main()
{
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
#ifdef SIGBREAK
signal(SIGBREAK, signal_handler);
#endif
while (!exit)
{
/* do something */
}
// Catch signal here
}
Take a look at https://stackoverflow.com/questions/298498/c-console-breaking. The standard library you need to use is csignal
What you can do is register for signals which force your app to close (SIGTERM) and perform logic there, like exiting your multiple threads. This post suggests that this should work with windows as well.
You could also register a function with atexit which seems to catch normal exit from main() etc, not sure if closing the terminal will count as "normal exit".
Edit: Ok so it seems you want to be notified as soon as the process exits. Sorry, I misread your question due to the term "exit value". Well if you start the process via CreateProcess() API, you should be able to do WaitForSingleObject() on the handle. This function will block until the process exited. So you can place all the code which you want to be executed after the process stopped after this call, and all should be fine.
If you in fact want the exit code of a process (return X in main()):
Programmatically, you can use GetExitCodeProcess() from WinAPI:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683189(v=vs.85).aspx
In the shell, use the %errorlevel% variable.
Related
I want to send SIGINT to a program started using QProcess.
I am working on ubuntu.
Source code of my process looks like this:
#include <iostream>
#include <csignal>
#include <stdlib.h>
#include <unistd.h>
void int_handle(int sig)
{
std::cout<<"Received SIGINT\n";
exit(0);
}
int main()
{
std::cout<<"Main called\n";
signal(SIGINT, int_handle);
while(1)
{
std::cout<<"Sleeping.....\n";
sleep(1);
}
return 0;
}
Compiled this program and generated executable my_prog
my Qprocess looks as shown below
QProcess* process= new Qprocess();
QString command = "my_prog";
process->start(command);
process->waitForStarted();
Based on some event I tried sending SIGINT in following ways
process->kill();
process->close();
process->write("0x03");
process->terminate();
kill(process->pid(), SIGINT);
QString command = kill -9 <PID>;
QByteArray ba = command.toLatin1();
system(ba.data());
Even after trying all these things I am not able to receive the SIGINT in my program.
Please help me in finding the correct way to implement this.
EDIT1: Updated the example program.
I tried to explain the problem and ignored syntax errors in the example.
Sorry for that.
Thanks in advance.
Besides from several syntax errors/typos in your example, which will prevent the code from even compiling, the program which you try to kill has two and a half issues:
The signal handler has the wrong signature, it receives an integer parameter as shown in the manpage. This won't even compile with g++.
In main no event loop or similar is started. Thus when you execute the binary, it registers the signal handler, and exits immediately after that, because signal() is non-blocking.
From the signal() manpage:
Avoid its use: use sigaction(2) instead.
Edit
Point 1 and 2 are obsoleted by EDIT1 of OP, point 3 remains.
As pointed out by Murphy, QProcess captures stdout/stderr and makes it available through a QIODevice interface. If you don't forward the subprocess output to the parent process, you won't see any output.
After forwarding the process channels, you must also send the correct signal if you want your signal handler to be called. The process->kill() sends a SIGKILL not a SIGINT, so your signal handler wouldn't be invoked. Most of your examples for killing the subprocess are sending the wrong signal.
Finally, be sure that your command is actually starting. I had to specify a relative local path ./my_prog in order to have the process start successfully.
Here is some code based on your incomplete example that works for me:
#include <QProcess>
#include <QDebug>
#include <unistd.h>
#include <csignal>
int main(int argc, char *argv[])
{
QProcess *process = new QProcess();
// Start process from local directory
QString command = "./my_prog";
// Forward output of process to parent stdout/stderr
process->setProcessChannelMode(QProcess::ForwardedChannels);
process->start(command);
// Ensure process starts successfully; wait indefinitely
if(process->waitForStarted(-1))
{
qDebug() << "Process started.";
// Wait a little before sending signal
sleep(1);
// Send the correct signal
kill(process->pid(), SIGINT);
} else {
qDebug() << "Failed to start process.";
}
}
Imagine the following program written in C:
void handler(int signo) {
write(STDOUT_FILENO, "handler\n", 8);
}
int main() {
signal(SIGUSR1, handler);
kill(getpid(), SIGUSR1);
write(STDOUT_FILENO, "after kill\n", 11);
}
If I run this program in Linux, is it possible the output is as follow:
after kill
handler
I tried many times, and the above result didn't appear.
If the SIGINT signal is delivered to the process after the puts("looping"); statement, then it will print the string "handler1" in the handle1 function. When the kill function returns, the output depends on when the SIGUSR1 signal will be delivered to the process. I think you can use the sigsuspend function to make sure it's what you want. By the way, before kill function returns, at least an unblocked signal is delivered to the process.
The following code outputs what you want and you need to block the SIGUSR1 signal first.
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void handler(int signo) {
write(STDOUT_FILENO, "handler\n", 8);
}
int main() {
sigset_t newmask, oldmask;
sigemptyset( &newmask );
sigaddset( &newmask, SIGUSR1 );
signal(SIGUSR1, handler);
// block the SIGUSR1 signal
sigprocmask ( SIG_BLOCK, &newmask, &oldmask );
kill(getpid(), SIGUSR1);
write(STDOUT_FILENO, "after kill\n", 11);
// reset the signal mask
sigprocmask ( SIG_SETMASK, &oldmask, NULL );
}
puts is not good inside signals handlers. Read signal(7), puts is not async-signal-safe. You should use write(2) inside a signal handler (not puts).
You have edited your question to use write instead of puts
And if you insist in wrongly using puts you should at least call fflush. But both are wrong inside signal handlers.
(Don't forget that stdoutis buffered)
BTW, it might happen (notably in multi-threaded application, where the signal handler is not running in the same thread that kill(2)-s the signal) that the signal handler is invoked after returning of kill
I'm not sure that you are guaranteed that the signal handler of a single-threaded process is returning before kill, even if I believe that would happen on most Linux kernels. What you should be sure is that the signal handler would eventually be called (but you cannot be sure on when exactly). Also, a kernel is permitted to lose some signals (e.g. if an external thing or process is sending a lot of same signals). So called POSIX real-time signals are the exception, not the norm (see also this)
If you have an event loop (e.g. around poll(2)) and accept to have Linux-specific code
you could consider using signalfd(2) and polling it inside your event loop.
I am writing a program dealing with Linux signals. To be more specific, I want to re-install signal SIGINT in child process, only to find that it doesn't work.
Here is a simpler version of my code:
void handler(int sig){
//do something
exit(0);
}
void handler2(int sig){
//do something
exit(0);
}
int main(){
signal(SIGINT, handler);
if ((pid = fork()) == 0) {
signal(SIGINT, handler2); // re-install signal SIGINT
// do something that takes some time
printf("In child process:\n");
execve("foo", argv, environ); // foo is a executable in local dir
exit(0);
}else{
int status;
waitpid(pid, &status, 0); // block itself waiting for child procee to exit
}
return 0;
}
When shell is printing "In child process:", I press ctrl+c. I find that function handler is executed without problem, but handler2 is never executed.
Could you help me with this bug in my code?
Update:
I want the child process to receive SIGINT signal during foo running process, is that possible?
It is not a bug - calling execve has replaced the running binary image. The function handler2() (and any other function of your binary) is no longer mapped in the program memory having been replaced by the image of "foo" and therefore all signal settings are replaced to a default.
If you wish the signal handler to be active during "foo" run, you have to:
make sure the handler function is mapped into the memory of foo
a signal handler is registered after "foo" starts.
One way to do this is to create a shared library that contains the signal handler and an init function that is defined as a constructor that registers said signal handler and force it into the "foo" memory by manipulating the environment under which you execve foo (the environ variable) to include
LD_PRELOAD=/path/to/shared_library.so
#gby's anwser has given comprehensive background knowlegde. I am here to give another solution without shared library.
Every time child process stops or terminates, parent process will receive SIGCHLD. You can handler this SIGCHLD signal to know if child process was terminated by SIGINT. In your handler:
pid_t pid = waitpid(pid_t pid,int * status,int options)
You can get status of child process through waitpid function.
if(WIFSIGNALED(status) && (pid == child_pid)){
if(WTERMSIG(status) == SIGINT){
// now you know your foo has received SIGINT.
// do whatever you like.
}
}
I'm trying to create a process in linux, however I keep getting an error. In my c++ code, I just want to open firefox.exe. Here's my code:
//header files
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
//main function used to run program
int main()
{
//declaration of a process id variable
pid_t pid;
//fork a child process is assigned
//to the process id
pid=fork();
//code to show that the fork failed
//if the process id is less than 0
if(pid<0)
{
fprintf(stderr, "Fork Failed");// error occurred
exit(-1); //exit
}
//code that runs if the process id equals 0
//(a successful for was assigned
else if(pid==0)
{
//this statement creates a specified child process
execlp("usr/bin","firefox",NULL);//child process
}
//code that exits only once a child
//process has been completed
else
{
wait(NULL);//parent will wait for the child process to complete
cout << pid << endl;
printf("Child Complete");
exit(0);
}
}
There is an error for the wait() function. I left this out and tried, but nothing happened.
You have to write:
execlp("/usr/bin/firefox","firefox",NULL);
You also need to put an _exit after execlp in case it fails.
I don't think that you have called execlp correctly.
It isn't going to append "firefox" to "usr/bin". Because it will search the PATH environment variable you can call it with execlp("firefox","firefox",NULL).
Aside: Yes, the exec family of functions allows you to break the nominal guarantee that argv[0] should name the executable. Sorry, that is just the way it is.
To create a process you can use system call, fork call, execl call.
TO know how to create process in linux using these call please follow the following link.
I think it will help you more to understand about process creations with example.
http://www.firmcodes.com/process-in-linux/
I am trying to automate the handler equipment(a robot picks a chip and put it onto a hardware platform) with the following requirement:
1.There are 6 sites for the handler , once handler puts a device onto that site, handler will return an errorcode:
code1 for ready to test, code2 for error, and if in process no code have returned.
2.There is a master PC that controls the handler operation, and the communication b/w master and site PCs are using Staf
3.I need to use that code to run some tests(which already implemented and working properly).
Handler puts the device in a FIFO order, first site returns code first, and last site returns code last.
4.The Site PC is acting passively, which master PC will determine when to run and how to run the tests. Site PC will only know if handler is ready then execute the tests.
So my question would be: In this case, for the site-PCs(Windows based with perl and .net enabled), is busy waiting method better or is the wait condition mechanism suits better:
For example: the sample code would be:
void runTestonSite()
{
for(;;)
{
if(returnCode == code1)
{
testStart(arg1,arg2,arg3);
}
}
}
or is there any better way to do this kind of task?
#include <boost/thread.hpp>
void getReturnCode() {
// do stuff
}
void RunTestOnSite() {
// do stuff
}
int main (int argc, char ** argv) {
using namespace boost;
thread thread_1 = thread(getReturnCode);
thread thread_2 = thread(RunTestOnSite);
// do other stuff
thread_2.join();
thread_1.join();
return 0;
}
Please advise,
thanks