this is my first post.
I have a task to use a fork to create multiple processes and then use execlp to run another program to add 2 numbers.
The problem I am having is we are supposed to use the exit() call in the execlp to return the small integer. This is a bad way to communicate but it's what we are supposed to do for the sake of this program.
Here is my "coordinator" program
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
using namespace std;
int main (int argc,char* argv[])
{
const int size = argc-1;
int sizeArray = 0;
int numofProc =0;
int arrayofNum[size];
int status;
int value;
for(int y=1; y<argc; y++)
{
arrayofNum[y-1] = atoi(argv[y]);
sizeArray++;
}
if(sizeArray % 2 !=0)
{
arrayofNum[sizeArray] = 0;
sizeArray++;
}
numofProc = sizeArray/2;
//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)
{
cout<<"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("./worker", "worker", arrayofNum[0], arrayofNum[1]);//child process
}
//code that exits only once a child
//process has been completed
else
{
waitpid(pid, &status, 0);
cout<<status;
}
//main
}
and here is the execlp process
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;
int main(int argc, char* argv[])
{
int arrayofNum[argc-1];
arrayofNum[0] = atoi(argv[1]);
arrayofNum[1] = atoi(argv[2]);
int sum = arrayofNum[0] + arrayofNum[1];
exit(sum);
}
My problem is NO MATTER WHAT I DO, the status is ALWAYS printing a 0, I do not know how to retrieve the sum that is returned from the worker process.
My professor told me ""Only the higher byte of status will have the value returned by the worker. you need to extract it. It can be done by many ways. ""
In a nut shell, my question is, How do I retrieve that "sum" that is being sent from my worker process.
Please, I am so confused and have been up for 2 nights wondering about this
Thanks,
John
First up, you need to pass strings to your program, but you say:
execlp("./worker", "worker", arrayofNum[0], arrayofNum[1]);
And arrayofNum is an array of integers. Also, with execlp you also need to pass a NULL as the last argument. The standard says:
The arguments represented by arg0,... are pointers to null-terminated
character strings. These strings shall constitute the argument list
available to the new process image. The list is terminated by a null
pointer.
Second, after you call to waitpid(2) you need to do:
if (WIFEXITED(status))
code = WEXITSTATUS(status);
Related
I write a simple c++ code. In my code, I create two threads, then I name the two threads TCPCall30003Proc and TCPCall30004Proc, but I can not find them using top command with option -H. My os is ubuntu 18.
#include <pthread.h>
#include <thread>
#include <stdio.h>
#include <time.h>
#include <iostream>
#include <stdlib.h>
#include <chrono>
#include <unistd.h>
void f1(int num)
{
printf("1\n");
while(1)
{
sleep(1);
}
}
void f2(int num)
{
printf("2\n");
while(1)
{
sleep(1);
}
}
int main(int argc, char **argv)
{
std::thread thd_1 = std::thread(f1, 1);
std::thread thd_2 = std::thread(f2, 1);
pthread_setname_np(thd_1.native_handle(), "TCPCall30003Proc");
pthread_setname_np(thd_2.native_handle(), "TCPCall30004Proc");
while(1)
{
sleep(1);
}
return 0;
}
From the pthread_setname_np manual page:
The thread name is a meaningful C language string, whose length is restricted to 16 characters, including the terminating null byte ('\0').
[Emphasis mine]
You names are 17 characters, including the null-terminator.
If you check what pthread_setname_np returns it should return -1 and with errno set to ERANGE.
You need to shorten your names.
I am making a shell and trying to understand the function of fork it (Only the code with issue is shown below).
However, After adding fork(); my shell is not exiting with the command exit. I know I can use kill(pid, SIGKILL) to achieve this but I do not want to show any exit status. I think exit(0); should work without the need of kill(pid, SIGKILL).
A simple explanation with the code would help a lot.
Update: I want to accept continuous commands until exit.
#include <iostream>
#include <sys/wait.h>
#include <vector>
#include <string>
#include <chrono>
#include <algorithm>
#include <unistd.h>
using namespace std;
typedef struct cmds{
string cmd;
} cmds;
bool operator<(cmds &as1, cmds &bs1){
return as1.durr<bs1.durr;
}
int main() {
vector <cmds> lst;
cmds ant;
string cmd;
pid_t pid = fork() ;
while (1){
if(pid==0){
cout<<"$>";
getline(cin,cmd);
ant.cmd=cmd;
string comd;
for(int i=0;i<cmd.length();i++){
if(cmd[i]!=' ')
comd+=cmd[i];
}
if(comd=="exit"){
exit(0);
}
else{
char s[256]="";
for (int i=0; i<cmd.length(); i++)
s[i]=cmd[i];
}
lst.push_back(ant);
}
else
wait(NULL);
}
}
**Expected output** - //The shell should end without any cout or exit status//
**Actual output** - //The shell does not end and you can type anything and enter and continue - however no '$' is present and you cannot use any shell commands//
Apologies for any messy writing - The new UI for writing questions is hard to use.
Your parent process is stuck in while(1) loop. Add break; line after wait(NULL);.
I am trying to link the output of a child process into the input of a parent process; the parent process is to execute a system call or command using the child's output.
I have looked to the following threads for answer; however, I didn't quite get the answer I am looking for.
Pipe - C++ piping issue
Linux Pipes as Input and Output
The problem I am having is that the command in the parent process is not being printed to the terminal.
Why isn't the output being printed to the terminal? I have closed the ends of my pipe in both the parent and child processes. Furthermore, the parent's std_out isn't being modified.
Here is my code.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
enum {RD, WR};
int fd[2];
pid_t pid;
if (pipe(fd) < 0)
perror("pipe error");
else if ((pid = fork()) < 0)
perror("fork error");
else if (pid == 0) { //In child process
close(fd[RD]);
dup2(fd[WR], STDOUT_FILENO);
close(fd[WR]);
execlp("/bin/ps", "ps", "-A", NULL);
}
else { //In parent process
close(fd[WR]);
dup2(fd[RD], STDIN_FILENO);
close(fd[RD]);
wait(NULL);
execlp("/bin/wc", "wc", "-l", NULL);
}
return 0;
}
You don't check for the failure of execlp.
Are you sure all of your programs are where you think they are? Your program works for me if I just change "/bin/wc" to "/usr/bin/wc".
I'm writing a fuzzer in C++ on linux. It spawns multiple threads and has a timeout function if the thread hangs for whatever reason. I cannot figure out the correct way to kill the thread off after it's timer runs out. What I am doing now is something along the lines of:
`
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <chrono>
#include <thread>
#include <stdlib.h>
#include <sys/wait.h>
#include <stdio.h>
#include <vector>
#include <iostream>
#include <sys/time.h>
#include <random>
#include <cstdlib>
#include <climits>
#include <sstream>
#include <iomanip>
#include <unistd.h>
#include <cstring>
#define READ 0
#define WRITE 1
void reaper (int c_pid, int t_timeout) {
std::this_thread::sleep_for(std::chrono::milliseconds(t_timeout));
kill (c_pid, 9);
}
FILE * popen2 (std::string command, std::string type, int & pid, std::string low_lvl_user) {
pid_t child_pid;
int fd[2];
pipe(fd);
if((child_pid = fork()) == -1) {
perror("fork");
exit(1);
}
if (child_pid == 0) { // child begins
if (type == "r") {
close(fd[READ]); //Close the READ
dup2(fd[WRITE], 1); //Redirect stdout to pipe
}
else {
close(fd[WRITE]); //Close the WRITE
dup2(fd[READ], 0); //Redirect stdin to pipe
}
if (getuid() == 0) {
execl("/bin/su", "su", "-c", "/bin/sh", "-c", command.c_str(), low_lvl_user.c_str(), NULL); // fixes not being able to reap suid 0 processes
}
else {
execl("/bin/sh", "/bin/sh", "-c", command.c_str(), NULL); // runs it all
}
exit(0);
}
else {
if (type == "r") {
close(fd[WRITE]); //Close the WRITE
}
else {
close(fd[READ]); //Close the READ
}
}
pid = child_pid;
if (type == "r") {
return fdopen(fd[READ], "r");
}
return fdopen(fd[WRITE], "w");
}
int pclose2(FILE * fp, pid_t pid) // close it so we don't fuck outselves
{
int stat;
fclose(fp);
while (waitpid(pid, &stat, 0) == -1) {
if (errno != EINTR) {
stat = -1;
break;
}
}
return stat;
}
int spawn_ch (std::string out_str) {
std::string low_lvl_user = "nobody";
int t_timeout = 500;
int pid; // initializes child
FILE * fp = popen2(out_str, "r", pid, low_lvl_user); // opens child process fork
char command_out[4096] = {0};
std::stringstream output;
std::thread reaper_thread(reaper, pid, t_timeout); // takes care of killing it off if it takes too long
reaper_thread.join();
while (read(fileno(fp), command_out, sizeof(command_out)-1) != 0) {
output << std::string(command_out);
memset(&command_out, 0, sizeof(command_out));
}
pclose2(fp, pid);
std::string token;
}
int main () {
std::string command = "HOME=AAAAAAAAA MAIL=AA /usr/sbin/exim4 -Ac AAAAAA -G -MCP,9,-Mar -Mf -Mset b -S 999999 -X,,-bF 999 -bdf -bpc -bpr -bpru,,-bt -exim4,AAA, -f,AAAAAAAAA,-oA -oMa,5Mu^i, -oMaa,, -oMas,,-oMs -oX isotanr -odb -oee -oem,999, -oo,99999999 -r 999999999 -t -ti 999999";
std::vector<std::thread> threads;
int num_threads = 2;
for (int cur_thread=1; cur_thread <= num_threads; ++cur_thread) threads.push_back(std::thread(spawn_ch, command)); // Thrift Shop
for (auto& all_thread : threads) all_thread.join(); // is that your grandma's coat?
exit(0);
}
But as the processes are spawned as suid 101 in this example (or 0, or whatever else), the kill function can be run as root to reap the processes it spawned... which would work, except exim4 apparently tries to spawn multiple processes, and when one dies the others don't. Is there a way to let the program know what processes were spawned to kill them, or preferably, a way to just terminate the entire thread that spawned them (which I think should work, as if you ctrl+c my program it will kill off what it spawned)?
The whole codebase is on github.
Thanks in advance.
The std::thread class provides no means to arbitrary terminate an active execution thread. This functionality is not implemented in the current C++ standard.
The sample code you posted is pretty much the only thing that can be done using purely the functionality in the C++ and C libraries.
The POSIX thread API is an alternative option. It does provide the means to terminate an active thread; however that comes with many important caveats, and it's very difficult to avoid undefined behavior, when terminating an execution thread using pthread_cancel(), since this will not properly unwind the terminated thread's stack, and invoke all the needed destructors; furthermore the executing thread must reach a cancellation point, in order for pthread_cancel() to take effect.
Additionally, if the executing thread execs another process, the new process is going to replace the thread's entire process, not just the executing thread's context. If this was your intent all along, trying to cancel the thread won't do much good anyway, and you pretty much have to do what you are already doing.
I am working on a project and I got it mostly figured out except for one minor(big) problem. I can't seem to figure out how to create pipes between any number of children.
for example I am taking in command line arguments to determine how many children will be produced. The first child doesn't have input but has output and the last child outputs to STD output. I need to pass values into the first child and into each child after that in order. Here is what i got:
#include <errno.h>
#include <cstdio>
#include <iostream>
#include <sys/wait.h>
using namespace std;
int main(int argc, char *argv[]) {
pid_t childpid;
int x2ypipe[2];
pipe(x2ypipe);
if(x2ypipe==0) {
cout<<"ERROR:"<<errno<<endl;
}
int y2zpipe[2];
pipe(y2zpipe);
if(y2zpipe==0) {
cout<<"ERROR:"<<errno<<endl;
}
pid_t xchild =fork();
if(xchild==0) {
dup2(x2ypipe[1],STDOUT_FILENO);
close(x2ypipe[0]);
close(x2ypipe[1]);
int a=execl(argv[1],argv[1], (char*)NULL);
if(a==-1) {
perror("The following error occurred at A");
}
}
for(int i=2; i<(argc-1); i++) {
childpid =fork();
if(childpid==0) {
dup2(x2ypipe[0],STDIN_FILENO);
close(x2ypipe[0]);
close(x2ypipe[1]);
//direct y2z pipe to standard output and replace the child with the program part2
dup2(x2ypipe[1],y2zpipe[1]);
dup2(y2zpipe[1],STDOUT_FILENO);
close(y2zpipe[0]);
close(y2zpipe[1]);
int b=execl(argv[i],argv[i],(char *)NULL);
if(b==-1) {
perror("The following error occurred at B");
}
}
}
pid_t zchild =fork();
if(zchild==0) {
dup2(y2zpipe[0],STDIN_FILENO);
close(y2zpipe[0]);
close(y2zpipe[1]);
int c=execl(argv[argc-1],argv[argc-1],(char *)NULL);
if(c==-1) {
perror("The following error occurred at C");
}
}
close(x2ypipe[0]);
close(x2ypipe[1]);
wait(NULL);
wait(NULL);
wait(NULL);
}
now right now I am only passing in three programs in to the argv[] and it works fine. I will have to add a if statement in my for loop to check for the last/highest possible value of i to connect the y2z pipe to the zchild. What I am having trouble doing it connecting the children to each other within the for loop. How would I go about creating a new pipe for each child from the last child?
Maybe this will help. Notice how I call pipe() inside my for loop, so I don't have to think of new "x2y", "y2z", "z2omega", etc, etc names for the pipe pairs.
Also notice how I used a variable prevfd from outside the for loop to carry the previous iterations's pipe file descriptor into the next iteration. And how it points to "/dev/null" to start with.
Finally, notice how I call wait() precisely as many times as I need to, in a loop, rather than writing it 3 (or 4 or 5 or ... 1,397) times.
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <cstdlib>
#include <cstdio>
#include <sys/wait.h>
int main(int argc, char *argv[]) {
int prevfd;
prevfd = open("/dev/null", O_RDONLY);
if(prevfd < 0) {
perror("/dev/null");
exit(1);
}
for(int i = 1; i < argc; ++i) {
int pipefd[2];
int kid;
if(i != argc-1 && pipe(pipefd)) {
perror("pipe");
break;
}
if(!fork()) {
dup2(prevfd, 0);
close(prevfd);
if(i != argc-1) {
dup2(pipefd[1], 1);
close(pipefd[0]);
close(pipefd[1]);
}
execl(argv[i], argv[i], (char*)0);
perror(argv[i]);
exit(1);
}
close(prevfd);
prevfd = pipefd[0];
close(pipefd[1]);
}
while(wait((int*)0) != -1)
;
return 0;
}
You need a separate pipe between each pair of connected processes.