Which function is used in C++ stdlib to exit from program execution with status code?
In Java, there's:
System.exit(0)
Assuming you only have one thread:
#include <iostream>
int main()
{
std::cout << "Hello, World!\n";
return(0);
// PROGRAM ENDS HERE.
std::cout << "You should not see this.\n";
return(0);
}
Output:
Hello, World!
The return(0); can be placed anywhere you like - it'll end int main(), and hence your program.
Alternatively, you can call exit(EXIT_SUCCESS); or exit(EXIT_FAILURE); from anywhere you like:
/* exit example */
#include <stdio.h>
#include <stdlib.h>
int main ()
{
FILE * pFile;
pFile = fopen("myfile.txt", "r");
if(pFile == NULL)
{
printf("Error opening file");
exit (1);
}
else
{
/* file operations here */
}
return 0;
}
In addition to the other responses you can also invoke abort, terminate, quick_exit (exits without calling destructors, deallocating etc; hence the name)
terminate calls abort by default but can call any terminate handler you set.
Example usage of abort and set_terminate (to se the handler used by terminate), quick_exit can be called (see example #2)
// set_terminate example
#include <iostream> // std::cerr
#include <exception> // std::set_terminate
#include <cstdlib> // std::abort
void myterminate () {
std::cerr << "terminate handler called\n";
abort(); // forces abnormal termination
}
int main (void) {
std::set_terminate (myterminate);
throw 0; // unhandled exception: calls terminate handler
return 0;
}
quick_exit/at_quick_exit example:
/* at_quick_exit example */
#include <stdio.h> /* puts */
#include <stdlib.h> /* at_quick_exit, quick_exit, EXIT_SUCCESS */
void fnQExit (void)
{
puts ("Quick exit function.");
}
int main ()
{
at_quick_exit (fnQExit);
puts ("Main function: Beginning");
quick_exit (EXIT_SUCCESS);
puts ("Main function: End"); // never executed
return 0;
}
I'm not entirely certain why one would call quick_exit but it exists and thus I should provide documentation for it (courtesy of http://www.cplusplus.com/reference )
Additionally one can call at_exit as the equivalent of at_quick_exit.
Admittedly I am not all that familiar with set_terminate and terminate as I don't call them myself, but I would guess you could use quick_exit as a terminate handler if you wanted; or a custom one (but please don't quote me on that).
In C++, you can use exit(0)
for example:
switch(option){
case 1:
//statement
break;
case 2:
//statement
exit(0);
Related
I'm trying to make a wrapper around an interactive program. For this I use the combination of pipe, dup2 and poll. All seems to go well until the child terminates. At this step the parent process appears to lose its stdin, which is what I can't seem to understand why.
Here's the code:
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <poll.h>
#include <fcntl.h>
#include <signal.h>
#include <vector>
#include <string>
#include <iostream>
struct SystemFunctionFailure
{
std::string what;
SystemFunctionFailure(std::string const& what) : what(what) {}
};
template<typename T,size_t N> constexpr size_t countof(const T(&)[N]) { return N; }
void readAndPrint(std::string const& what, int fd)
{
std::cerr << "Reading "+what+"\n";
std::vector<char> buffer(1024);
const auto bytesRead=read(fd,buffer.data(),buffer.size());
if(bytesRead==-1)
{
if(errno!=EAGAIN)
throw SystemFunctionFailure("read "+what);
}
else if(bytesRead==0)
{
std::cerr << "EOF reached on "+what+"\n";
exit(0);
}
else
std::cerr << "CONTENTS OF "+what+": "+std::string(buffer.data(),buffer.size())+"\n";
}
int main()
{
try
{
int pipeChildOut[2];
if(pipe(pipeChildOut)==-1) throw SystemFunctionFailure("pipe for child stdout");
int pipeChildErr[2];
if(pipe(pipeChildErr)==-1) throw SystemFunctionFailure("pipe for child stderr");
int pipeChildIn[2];
if(pipe(pipeChildIn)==-1) throw SystemFunctionFailure("pipe for child stdin");
const auto child=fork();
if(child==-1) throw SystemFunctionFailure("fork");
if(child)
{
dup2(pipeChildOut[1],STDOUT_FILENO);
close(pipeChildOut[0]);
dup2(pipeChildErr[1],STDERR_FILENO);
close(pipeChildErr[0]);
dup2(pipeChildIn[0],STDIN_FILENO);
close(pipeChildIn[1]);
execlp("sh","sh","-c","sleep 1; echo Test ; sleep 1; echo Child is exiting... >&2",nullptr);
throw SystemFunctionFailure("execlp returned");
}
else
{
const int childStdErr=pipeChildErr[0];
const int childStdOut=pipeChildOut[0];
dup2(pipeChildIn[1],STDOUT_FILENO);
fcntl(childStdErr,F_SETFL,O_NONBLOCK);
fcntl(childStdOut,F_SETFL,O_NONBLOCK);
fcntl(STDIN_FILENO,F_SETFL,O_NONBLOCK);
while(true)
{
std::cerr << "New iteration of IO loop\n";
pollfd pollfds[]={ // making the indices coincide with .._FILENO
{STDIN_FILENO,POLLIN},
{childStdOut,POLLIN},
{childStdErr,POLLIN},
};
if(poll(pollfds,countof(pollfds),{-1})==-1)
throw SystemFunctionFailure("poll");
std::cerr << "poll returned\n";
for(unsigned i=0;i<countof(pollfds);++i)
std::cerr <<" pollfds["<<i<<"].revents: " << pollfds[i].revents << "\n";
if(pollfds[ STDIN_FILENO].revents&POLLIN) readAndPrint("stdin" ,pollfds[ STDIN_FILENO].fd);
if(pollfds[STDOUT_FILENO].revents&POLLIN) readAndPrint("stdout",pollfds[STDOUT_FILENO].fd);
if(pollfds[STDERR_FILENO].revents&POLLIN) readAndPrint("stderr",pollfds[STDERR_FILENO].fd);
}
}
}
catch(SystemFunctionFailure& ex)
{
perror(ex.what.c_str());
exit(EXIT_FAILURE);
}
}
Here the child closes its original stdin implicitly via dup2, so it seems it shouldn't affect any accesses of the parent to the console input. But for some reason here's what I get as output:
$ g++ test.cpp -o test -std=c++14 && ./test
New iteration of IO loop
poll returned
pollfds[0].revents: 0
pollfds[1].revents: 1
pollfds[2].revents: 0
Reading stdout
CONTENTS OF stdout: Test
New iteration of IO loop
poll returned
pollfds[0].revents: 0
pollfds[1].revents: 0
pollfds[2].revents: 1
Reading stderr
CONTENTS OF stderr: Child is exiting...
New iteration of IO loop
$
I.e. I get the shell prompt, so the parent isn't in the foreground anymore. After this, if I wait several seconds and type a letter, I get this output:
poll returned
pollfds[0].revents: 1
pollfds[1].revents: 0
pollfds[2].revents: 0
Reading stdin
read stdin: Input/output error
I'd like to at least have the parent process retain access to its console input after the child dies. After reading an answer to another question, I think my problem is related, but that answer doesn't answer my question: "How to do it right?".
I think if(child) should be if(child == 0).
From https://linux.die.net/man/2/fork
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child. On failure, -1 is returned in the
parent, no child process is created, and errno is set appropriately.
I'm having an issue with a process being stuck on wait. I've been troubleshooting this issue and its the only bug i have currently for my shell program.
The problem is the program should exit when the user enters "exit". However it seems if the user enters an invalid string the program gets stuck on wait(). this results in having to type exit twice to exit instead of once. How do I stop this from happening, how do i exit from the wait() call when a user enters a dumb string?
Steps to reproduce:
compile and run with gcc/g++
type in an expletive of your choice
type exit
notice the program doesnt exit (because its stuck on wait() but prompting
type exit again
program exits
#include <iostream>
#include <unistd.h>
#include "stdlib.h"
#include "stdio.h"
#include <iostream>
#include <string>
#include <sys/wait.h>
#include <sstream>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
using std::string;
using std::cout;
using std::endl;
bool exitstatus;
int argsIndex = 0;
pid_t pid;
int main(void)
{
char * args[100];
string check = "";
while(exitstatus==false)
{
cout<<"tinyshell:~>";
std::getline(std::cin, check);
if(check == "exit"){
exitstatus==true;
}
if(exitstatus==false&&check!="cd..")
{
pid = fork();
perror("");
if (pid < 0) { /* error occurred */
fprintf(stderr, "Fork Failed");
//return 1;
}
else if (pid == 0 ) { /* child process */
execvp(args[0],args);
perror("");
}
else if(check!= "&"){/* parent will wait for the child to complete */
wait(NULL);
perror("");
// cout <<"Child Complete" << endl;
}
else
{
}
}
}
return 0;
};
It may have to do something with this line:
exitstatus==true;
Did you, by any chance meant:
existatus = true;
gcc reports something like this for it anyway (-Wall):
warning: statement has no effect [-Wunused-value]
exitstatus==true;
That's a pretty nice example showing why enabling warnings is a good practice ...
There's also a more subtle problem with your code. You're not checking the result of your execvp function. So basically if you enter some garbage command in your shell your exec will fail but your child process will continue running the same code as the parent (the loop).
Just add an exit(EXIT_FAILURE); after your execvp() call.
In the following, the child process creates the object. It uses signal to kill itself after certain period of time:
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
class Wut{
public:
Wut(){cout<<"obj being created" << endl;}
~Wut(){cout<<"obj being destroyeed" << endl;}
};
void alarmHandler(){
cout << "Alarm! Forcing child to kill itself" << endl;
kill(getpid(), SIGKILL);
}
int main(int argc, char* argv[]){
int status;
pid_t pid;
if((pid = fork()) == 0){
Wut hi;
signal(SIGALRM, (sighandler_t)alarmHandler);
alarm(1);
alarm(7);
sleep(10);
cout << "this will not get printed" << endl;
} else {
wait(&status);
cout << "Parent dies" << endl;
}
sleep(10);
return 0;
}
But I am not sure if the object it creates gets destroyed properly because it never calls the destructor.
The KILL signal is actually not sent to the process; it's a signal for the operating system to forcibly stop the program execution. That means that destructors will not be called.
Use a signal like SIGTERM to see the expected behaviour:
kill(getpid(), SIGTERM);
Unix processes can't handle SIGKILL in any way. Your process is dead as a doornail, immediately. If you want a graceful exit, look into SIGTERM. You can then register a handler to do whatever cleanup you need.
You can use the handler to put your program into a state where it exits normally (e.g. by setting a flag or such), allowing the destructors to run.
SIGKILL is (in most cases) the same as kill -9, so all of the memory allocated to that process is reclaimed by the operating system.
Here is the code on which I set my handler for SIGABRT signal then I call abort() but handler does not get trigered, instead program gets aborted, why?
#include <iostream>
#include <csignal>
using namespace std;
void Triger(int x)
{
cout << "Function triger" << endl;
}
int main()
{
signal(SIGABRT, Triger);
abort();
cin.ignore();
return 0;
}
PROGRAM OUTPUT:
As others have said, you cannot have abort() return and allow execution to continue normally. What you can do however is protect a piece of code that might call abort by a structure akin to a try catch. Execution of the code will be aborted but the rest of the program can continue. Here is a demo:
#include <csetjmp>
#include <csignal>
#include <cstdlib>
#include <iostream>
jmp_buf env;
void on_sigabrt (int signum)
{
signal (signum, SIG_DFL);
longjmp (env, 1);
}
void try_and_catch_abort (void (*func)(void))
{
if (setjmp (env) == 0) {
signal(SIGABRT, &on_sigabrt);
(*func)();
signal (SIGABRT, SIG_DFL);
}
else {
std::cout << "aborted\n";
}
}
void do_stuff_aborted ()
{
std::cout << "step 1\n";
abort();
std::cout << "step 2\n";
}
void do_stuff ()
{
std::cout << "step 1\n";
std::cout << "step 2\n";
}
int main()
{
try_and_catch_abort (&do_stuff_aborted);
try_and_catch_abort (&do_stuff);
}
Although you can replace handler for SIGABRT and abort() will pay attention to the handler, the abort is only inhibited if the signal handler does not return. The relevant quote in C99 is in 7.20.4.1 paragraph 2:
The abort function causes abnormal program termination to occur, unless the signal SIGABRT is being caught and the signal handler does not return. ...
Your signal handler does return and thus the program is aborted.
You get those symptoms i.e. the popup debug dialog, when you have a debug build (with windows and Visual Studio- I'm testing with 2012 version), since it sets a debug break, in the debug implementation of abort() ).
If you pick "ignore" you get that message "Function triger"
If you do a release build, then you don't get the debug popup dialog, and you get the message, as expected
#include <iostream>
using namespace std;
#include <exception>
void dis()
{
cout<<"terminate disabled "<< endl;
}
void display() throw(int,double)
{
if(0)
throw int();
if(0)
throw double();
if(1)
throw string();
}
int main()
{
set_unexpected(dis);
try
{
display();
}
catch(int)
{
cout<<"int "<< endl;
}
catch(double)
{
cout<<"double "<< endl;
}
catch(string)
{
cout<<"string "<< endl;
}
system("pause");
return 0;
}
now the output was
terminate disabled
and then the program terminated
but instead of set_unexpected when i wrote
set_terminate(dis);
the output was
terminate disabled
terminate disabled
why this dicrepancy?
So, it's not entirely clear what your original output was. I tried to clean it up as best as I could, but your quote tags make it unobvious.
In your code, if you use set_unexpected(dis), you should see:
terminate disabled
In your code if you use set_terminate(dis), you should see:
terminate disabled
In your code, if you use both set_unexpected(dis) and set_terminate(dis), you should see:
terminate disabled
terminate disabled
One way to get around this, is to have dis throw 0 as the last line. That would allow you to convert your exception to something that your function claims that it will throw.