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/
Related
I am learning message queues, wrote code to create message queue
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <errno.h>
int main()
{
key_t key;
int msgid;
key = ftok("proj", 64);
if (key == -1) {
perror("ftok failed");
exit(1);
}
printf("key:%x\n", key);
//IPC_CREAT: creating message queue if not exists
msgid = msgget(key, IPC_CREAT);
if (msgid == -1) {
perror("msgget failed");
printf("errno:%d\n", errno);
if (errno == ENOENT)
printf("No message queue exists for key and msgflg did not specify IPC_CREAT\n");
exit(2);
}
printf("msgid:%x\n", msgid);
return 0;
}
Running the command did not show output: ipcs -q
panther2#ubuntu:~/c_codes/msg_queue$ ipcs -q
------ Message Queues --------
key msqid owner perms used-bytes messages
Can you guys please tell me if i am making any mistake
As I see there is nothing wrong with your code, but the behavior is really strange, even on my system.
As mssget returns 0, everything is ok ( it should return a non negative number which 0 is ) and the queue can be used.
I added a for(;;); at the end of your prog and start it again. ipcs now shows:
0x4025077b 0 krud 0 0 0
After I ipcrm -q 0 and start the program again, I got a new id for each run. I now removed the endless loop and all and everything still works, every run I got a message queue with different number which I always have to destroy before next run.
That is really strange!
I found a lot reports on that topic, e.g.:
https://www.unix.com/programming/248572-msgget-2-returns-0-workaround-fix.html
http://forums.codeguru.com/showthread.php?403036-strange-problem-in-using-msgget%28%29-in-Linux
Keep us informed if you have found a valid solution!
As my system now generates at every run a new message queue with a id > 0, I can't reproduce this behavior anymore. I did not want to reboot again ;)
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.";
}
}
Visual C++ 2017 -- Console application
The only documentation I find for the Windows version of popen, namely _popen, says it is supposed to return a null_ptr when it fails. It says nothing about spewing a gratuitous error message to the console. Yet if returns non-null and spews. I have not found a way to determine if the pipe connected. When I use fprintf to write to the bad pipe, it does not appear to fail either. Is this a bug in _popen, or am I doing it wrong? What is the workaround?
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
int main()
{
// This program is expected to write
// 00000000
// Good
//
// Instead it writes (e.g.), in this order,
// 0082F2C0
// Not good
// '42' is not recognized as an interal or external command,
// operable program or batch file.
FILE* fp = _popen("42 is a no-good command", "w");
std::cout << fp << std::endl;
if (!fp) {
std::cout << "Good" << std::endl;
}
else {
std::cout << "Not good" << std::endl;
}
return 0;
}
Your call to _popen() succeeds because it is executing whatever command you pass it within the context of a spawned copy of the command processor (the Command Prompt, usually cmd.exe).
(See Remarks section here: _popen, _wpopen).
You can prove/recreate this by just opening a Command Prompt and typing your "42 is a no-good command".
You should get the exact same error that is being produced by your program.
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 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.