run background process linux simple shell. C++ - c++

I'm creating a simple shell in linux and I'm having trouble getting a command to run in the background.
here is my code so far:
create command,argv and check if it is to be ran in the background &
enter this code:
if(strcmp(command,"cd")==0)
{
chdir(argv[1]);
}
else if(strcmp(command,"clr") == 0)
{
if ((pid = fork()) == 0)
{
execvp("clear",argv);
}
wait(&status);
}
else
{
if ((pid = fork()) == 0)
{
execvp( prog, argv );
}
wait(&status);
}
command and argv are what I get from the user.
I need to run a command in the background if '&' is the last part of the command. I have already checked for that with a boolean var of bg. but I'm having trouble with the WAITPID() function im not sure where it goes.

I guess your issue is if you end up calling waitpid() directly, you will block, and the process is not really running in the background. You can handle this in two ways.
Choice 1: Avoid the issue. After calling fork once, have the child fork one more time. Let the grandchild execute the command, and let the child exit. The parent waits on the child like before, but the grandchild is executing the command in the background. The grandchild process will be reaped by the init process.
Choice 2: Notice the asynchronous notification that the child is done. When a child process dies, the parent process will receive the SIGCHLD signal. Have a signal handler notice this signal and reap the child. This might require that you restructure your code so that the synchronous waiters actually receive a synchronous notification from your signal handler. You would then need a mechanism for the signal handler to distinguish between foreground and background children, and only send synchronous notifications for the foreground children.

Related

Any way to tell when forked/exec'd Qt application's main window is being displayed?

I have a launcher application which will fork and exec a Qt application when the user clicks on the relevant icon.
For visual feedback, I want to display a wait cursor from the time when the user selects an icon, until the requested app's main window is on-screen.
void RocketLauncher::onItemSelect(QListWidgetItem* item)
{
QApplication::setOverrideCursor(Qt::WaitCursor);
const AppConfig& app = getAppConfig(item);
forkAndExec(app.cwd(), app.cmd(), app.args(), app.env());
// TODO: wait until app's main window is being displayed
QApplication::restoreOverrideCursor();
}
The problem that I'm having is that in my launcher app, I get back the child process's pid from fork immediately, but it still takes some time for the child process to exec and for its main window to show up on-screen.
As such, my call to QApplication::restoreOverrideCursor() executes immediately, and there is no visual cue to the user that the application is still being launched.
Is there some way I can get signalled that the child is running?
I can see two ways to implement this:
With explicit inter-process communication. The child app can tell the launcher app once its main window has been created, for example via a DBus call, standard output, shared memory or any other of the many IPC mechanisms available. There is a startup notification library for X11 that uses explicit IPC by passing X messages, used by KDE and GNOME.
Depending on the OS and the used window manager in there, you might be able to ask the window manager for a list of opened windows and be notified when a new window is created. I don't think there is a Qt API for that, you'd need to use platform-specific code. For X11, you'd do something similar to the xwininfo program. Also, there is a LGPL-licensed KDE Frameworks API for this called KWindowSystem, which has a windowAdded signal. I haven't check on which platforms this is actually implemented, the docs suggest at least X11 and Mac OS.
I suggest you start a thread (with QtConcurrentRun and handled with QFutureWatcher) which is responsible for starting child process and waiting for the end displaying GUI. This mechanism can be done using a pipe in wich you send data from the place in child code where you believe that the GUI is displayed (catch showEvent() or the end of the MainWindow constrcutor...). The thread in parent process must sleep until receiving data on the pipe for waking up.
there is a lot of example of using pipe in linux. Also you can use Unix socket, shared memory or other IPC or maybe you can test with creatin a file in /tmp but is a bad idea.
Another simple idea is to proceed with QProcess and write from your new program some string on standard output to signal end of GUI display (to test...):
bool Class::startExternalProgram(QString _file)
{
QtConcurrent::run(this, &Class::starting, _file);
return true;
}
bool Class::starting(QString file)
{
QProcess *p = new QProcess;
params << file;
p->start("your program", params);
if (!p->waitForStarted(5000)) {
p->close();
delete p;
crashFinish(1, QProcess::CrashExit);
return false;
}
else {
processes.push_back(p);
/*to handle crash*/
QObject::connect(p, SIGNAL(finished(int,QProcess::ExitStatus)),
this, SLOT(crashFinish(int, QProcess::ExitStatus)));
p->waitForReadyRead(600000);/*10mn*/
... /*handle timeout here*/
return true;
}
}
void Class::crashFinish(int, QProcess::ExitStatus) {
auto p = qobject_cast<QProcess*>(QObject::sender());
...
}

Application does not exit on logout

I would like to ask what is the signal that is called when the user logs out? I have a Qt gui app that has handler for SIGTERM and SIGHUP signals. The app also has its own close event handler, so user can't close it by clicking on "X". The problem is that when the user logs out then the ubuntu hangs (the icon from taskbar disappears but the process keeps running) and does not let the user log out because (imo) it waits for the process to be terminated. When I use kill -15 'myapp' command then the app closes normally as it is supposed to so the problem shouldn't be in my handler.
static int setupHandlers(){
struct sigaction hup,term;
hup.sa_handler = signalHandler;
sigemptyset(&hup.sa_mask);
hup.sa_flags = 0;
if (sigaction(SIGHUP, &hup, 0) > 0){
return 1;
}
term.sa_handler = signalHandler;
sigemptyset(&term.sa_mask);
if (sigaction(SIGTERM, &term, 0) > 0){
return 2;
}
return 0;
}
signalHandler just calls exit(0) (also tried _exit(0) and abort())
There are 3 standart terminating signals, that you can handle - SIGINT, SIGQUIT and SIGTERM. Try to subscribe to each one of them and look.
signalHandler just calls exit(0) (also tried _exit(0) and abort())
You rather need to tell Qt to exit. Your signal handler need to have a reference on the application object and call QCoreApplication::exit(0);.
Whether it is by SIGTERM or by the user user input, your application need to nicely handle termination requests. In particular ensure that all objects which launch a process or a thread are cleanly destroyed when it happens. The classic code inspired from QtCreator :
d->m_guiProcess.terminate();
if (!d->m_guiProcess.waitForFinished(1000)) { // This is blocking, so be fast.
d->m_guiProcess.kill();
d->m_guiProcess.waitForFinished();
}
The code executing this need to stop, so it first forward nicely a SIGTERM (terminate), wait for small amount of time and then ask rudely with a SIGKILL (kill).

asynchronous c++ inter-process control

I'm writing this with c++ on Ubuntu 12.04 LTS and i am explicitly not using any BOOST libraries.
What I want to do is have a parent process and two or more children run simultaneously.
The parent process acts like an event listener and task dispatcher. The children handle the tasks the parents tells them to; these tasks are system calls, and the parent doesn't care when they finish.
What I have done successfully so far is
parent will fork() some children and retain their pids
children are suspended (S) immediately after being fork() with pause()
parent resumes (R) and detects events in a standard event loop way
what I need to know next is how to resume a child and return to the parent while child is still running.
So my questions are, can a parent and child run simultaneously and safely in this manner? (where the parent doesn't care what the child is doing after its resumed)
What do I have to do to in general to resume a child process after a pause()?
below is the constructor function that forks the children
childManager(int number_of_children, pid_t parent) {
int i=0;
while(number_of_children--) {
if(parent == getpid())
{
this->parent = parent;
children.push_back({++i,_IDLE,fork()});
if(parent != getpid()) pause();
}
}
}
The only question I see here is
What do I have to do to in general to resume a child process after a pause()?
Send it a signal whose action is either to execute a signal-catching function or terminate the process. For example:
kill(children[i], SIGUSR);
That said, this is a less than ideal way to do this. You could just as easily have the children block on a pipe waiting for the parent to tell them to do something. Or about 30 similar things which don't involve signals.
To answer your specific questions:
So my questions are, can a parent and child run simultaneously and safely in this manner? (where the parent doesn't care what the child is doing after its resumed)
The parent process will have to call wait or waitpid to harvest the child processes after they exit. If you do not do that you will be left with zombie processes. You can do this in a nonblocking way inside your event loop in the parent process.
What do I have to do to in general to resume a child process after a pause()?
You have to send a signal to the child process. You do this by calling kill in the parent process. You will need to install a signal handler in the child process to catch the signal - use sigaction for that.

Notification to a parent process

When using the fork system call, I have seen that many a times that the parent calls waitpid so that the child can finish.
My question here is does the child send a notification to the parent preocess. Without using any shared resource, how can a parent identify that the chils has been completed?
The OS sends a SIGCHLD to the parent when the child exits. You can choose to poll waitpid() using WNOHANG, or to just check with wait() after receiving a SIGCHLD. The child process doesn't need to do anything in particular, this is all managed by the OS.
In Linux Operating system, every child is having some parent and even if the parent dies before the child, the child is inherited by init(PID:1) process. This thing is done so that there should not any zombie process(process entry is there in the process table but process is actually already died) which is taking memory space for no use.
The kernel keeps an eye on all the processes which are died either due to their complete execution or due to some other reason(like invalid memory access) and retains some information like child's exit status. When the child terminates a SIGCHLD signal is sent to the parent. By default the signal is simply ignored. However commonly wait() system call implemented in a handler for the SIGCHLD, so that the parent may act upon the exit status of the child.
In addition to receiving SIGCHLD as mentioned by Erik, you can poll the child for events of interest by using WNOHANG. Here's an example:
pid_t pid = fork();
if (pid) {
while (1) {
int status;
int waitpid(pid, &status, WNOHANG);
if (pid == waitpid && WIFEXITED(status))
break;
// do other stuff
}
}

send SIGINT to child process

I am trying to create a child process and then send SIGINT to the child without terminating the parent. I tried this:
pid=fork();
if (!pid)
{
setpgrp();
cout<<"waiting...\n";
while(1);
}
else
{
cout<<"parent";
wait(NULL);
}
but when I hit C-c both process were terminated
Don't use CTRL-C, this sends a signal to all processes with the same controlling terminal (ie, in the same session). That's something that setpgid doesn't change though I think there's a setsid (set session ID) call for that purpose.
The easiest solution is simply to target the specific process rather than a session. From the command line:
kill -INT pid
From C:
kill (pid, SIGINT);
where pid is the process ID you want to send the signal to.
The parent can get the relevant PID from the return value from fork(). If a child wants its own PID, it can call getpid().
Aha, the mystery of process groups and sessions and process group leaders and session group leaders appears again.
Your control/C sent the signal to a group. You need to signal an individual pid, so follow paxdiablo's instructions or signal ("kill") the child from the parent. And don't busy wait! Put a sleep(1) in the loop, or better yet, one of the wait(2) system calls.
You could try implementing a SIGINT signal handler which, if a child process is running, kills the child process (and if not, shuts down the application).
Alternatively, set the parent's SIGINT handler to SIG_IGN and the child's to SIG_DFL.