How to use the function of "CreatePipe" and "CreateProcessW" in Linux, when I compile the C++ code in Linux, there have some errors as follow: 'CreatePipe' was not declared in this scope. 'CreateProcessW' was not declared in this scope.
Posix/Linux:
int pipe(int pipefd[2]);
pipefd[0] refers to the read end of the pipe.
pipefd[1] refers to the write end of the pipe.
Linux specific:
int pipe2(int pipefd[2], int flags);
When it comes to CreateProcess, the Posix/Linux version is done in a few steps.
Call fork() to create a new process - still running the same program - so two processes will now continue running the same program from the same point where fork() was called. Determining if it's the parent process or child process is done by checking the return value (the process id) from fork().
dup the file descriptors returned by pipe using int dup2(int oldfd, int newfd); to replace stdin and stdout for the new process.
Execute a program in the new process using one of the exec* functions.
// create pipes here
if(pid_t pid = fork(); pid == -1) {
// fork failed
} else if(pid == 0) { // child process goes here (with a new process id)
// dup2(...)
// exec*()
} else { // parent process goes here
// do parenting stuff
}
Example:
#include <unistd.h>
#include <sys/types.h>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <stdexcept>
struct Pipe {
Pipe() {
if(pipe(io)) throw std::runtime_error("pipe failure");
}
~Pipe() {
close_rd();
close_wr();
}
void close_rd() { closer(io[0]); }
void close_wr() { closer(io[1]); }
int rd() { return io[0]; }
int wr() { return io[1]; }
private:
void closer(int& fd) {
if(fd != -1) {
close(fd);
fd = -1;
}
}
int io[2];
};
int main() {
Pipe parent_write, parent_read;
if(pid_t pid = fork(); pid == -1) {
// fork failed
return 1;
} else if(pid == 0) { // child process goes here (with a new process id)
// close file descriptors we don't need:
parent_write.close_wr();
parent_read.close_rd();
// duplicate into the place where stdin/stdout was
dup2(parent_write.rd(), fileno(stdin));
dup2(parent_read.wr(), fileno(stdout));
// execute a program
execl("/bin/ls", "/bin/ls", nullptr);
// exec* functions never returns if successful, so if we get here, it failed:
std::exit(1);
} else { // parent process goes here
std::cout << "child process " << pid << " started\n";
}
// close file descriptors we don't need:
parent_write.close_rd();
parent_read.close_wr();
// read data from child process using the file descriptor in parent_read.rd()
char buf[1024];
ssize_t rv;
while((rv = read(parent_read.rd(), buf, 1024))) {
write(fileno(stdout), buf, static_cast<size_t>(rv));
}
// use write(parent_write.wr(), ...) to write to the child.
}
Related
I know wait(NULL) waits for all child process to terminate. But while working with fork(),execv()/execvp() and wait(), it seems wait(NULL) is not waiting for all the child processed to terminate.
I was trying to understand the unexpected behaviour of the wait(NULL) system call in my code.
I tried to recreate the same situation with a different but smaller code, it is shown below.
#include <unistd.h>
#include <filesystem>
#include <sys/wait.h>
#include <bits/stdc++.h>
#include <fcntl.h>
using namespace std;
int main ()
{
int pid;
int fd[2];
char command[] = "square";
//constructing a pipe
if(pipe(fd)==-1)
cout<<"Pipe1 Failed";
//first fork
pid = fork();
if(pid<0)
{
cout<<"fork failed";
}
else if(pid == 0)
{
cout<<"inside child 1\n";
close(0);
//opening input file at fd = 0
if(open("input",O_RDONLY) != 0)
cerr<<"Failed input open\n";
//connecting write end of pipe to first child process
dup2(fd[1],1);
close(fd[1]);
close(fd[0]);
char *args[] = {command,NULL};
//calling exec system call
execv(command,args);
cerr<<"execv1 failed\n";
exit(0);
}
//second fork
pid = fork();
if(pid<0)
{
cout<<"fork failed";
}
else if(pid == 0)
{
cout<<"inside child 2\n";
//connecting read end of the pipe to second child process
dup2(fd[0],0);
close(fd[0]);
close(fd[1]);
char *args[] = {command,NULL};
//calling exec system call
execv(command,args);
cerr<<"execv2 failed\n";
exit(0);
}
wait(NULL);
cout<<"After wait\n";
return 0;
}
What this code effectively tries to do is something like ./square < input | ./square in bash. input is a file that contains a number (it was 5 when I ran the code), square is a function that takes an integer input and prints its square (n*n).
The code of square is
#include<stdio.h>
int main()
{
int n;
scanf("%d",&n);
printf("%d",n*n);
return 0;
}
The final output I was expecting is (with input file containing number 5)
inside child 1
inside child 2
625
After wait
But the final output I am getting is
inside child 1
inside child 2
After wait
625
Output image
Can somebody help me figure out what is happening here or where my understanding is wrong.
NOTE: I used g++ compiler to compile this C++ codes.
Thanks in advance.
wait(NULL) doesn't wait for all children to exit. wait(&wstatus) waits for one child, and puts its exit status into the int wstatus. wait(NULL) waits for one child, and ignores its exit status.
Citation: man 2 wait
I wanted to do this problem but I cannot take input message:
Create a program that does the following:
1.Create a parent and a child process
2.The parent process reads a number from keyboard and sends it to the child
3.The child calculates if the given number is prime or not and prints the result on screen
This is my code:
#include <iostream>
#include <unistd.h> // for fork()
#include <string.h> // for strerror()
#include <sys/wait.h>
#include <sys/types.h>
using namespace std;
bool isprime(int number);
int main()
{
int num;
pid_t pid;
int fd[2];
char buffer[100];
pipe(fd);
pid = fork();
//parent process
if (pid > 0)
{
cin>>num;
write(fd[1], &num, sizeof(num));
close(fd[1]);
int status;
//Do not check for errors here
wait(&status);
}
//child process
else if (pid == 0)
{
read(fd[0], buffer, 100);
close(fd[0]);
if (isprime(num))
{
cout<<"number is prime";
}
else
{
cout<<"number is not prime";
}
return EXIT_SUCCESS;
}
else
{
cout << "fork() failed (" << strerror(errno) << ")" << endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
bool isprime(int number)
{
if (number < 2)
return false;
if (number == 2)
return true;
for (int i = 2; (i*i) <= number; i++)
{
// Take the rest of the division
if ((number % i) == 0)
return false;
}
return true;
}
this my result of run
Using a pipe along with fork is not that hard, but you must respect some rules:
each part should close the handle that it does not use. Not doing it is a key for future problems
starting from the fork, changes in one process are not reflected in the other one
Your code should become:
...
//parent process
if (pid > 0)
{
close(fd[0]); // close the part that only the other process will use
cin>>num;
write(fd[1], &num, sizeof(num));
close(fd[1]);
int status;
//Do not check for errors here
wait(&status);
}
//child process
else if (pid == 0)
{
close(fd[1]); // close the part used by the other process
read(fd[0], &num, sizeof(num)); // read into num what the parent has written
close(fd[0]);
...
In real world code, you should check that every read is successfull (both from cin and from the pipe...)
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 m trying to implement a program using pipes where parent process accepts a string and passes it to child process. Need to be done with only single pipe. How does the pipe read & write accepts string.
Here is my sample code! all!
#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
using namespace std;
int main()
{
int pid[2];
ssize_t fbytes;
pid_t childpid;
char str[20], rev[20];
char buf[20], red[20];
pipe(pid);
if ((childpid = fork()) == -1) {
perror("Fork");
return(1);
}
if (childpid == 0) {
// child process close the input side of the pipe
close(pid[0]);
int i = -1, j = 0;
while (str[++i] != '\0') {
while(i >= 0) {
rev[j++] = str[--i];
}
rev[j] = '\0';
}
// Send reversed string through the output side of pipe
write(pid[1], rev, sizeof(rev));
close(pid[0]);
return(0);
} else {
cout << "Enter a String: ";
cin.getline(str, 20);
// Parent process closing the output side of pipe.
close(pid[1]);
// reading the string from the pipe
fbytes = read(pid[0], buf, sizeof(buf));
cout << "Reversed string: " << buf;
close(pid[0]);
}
return 0;
}
You never pass the string to be reversed to the child, so it reverses some random garbage and sends it to the parent.
Minor issues:
write(pid[1], rev, sizeof(rev));
close(pid[0]); // Should be pid[1]
return(0); // Should be _exit(0)
The reason you don't want to return from main in the child is that you don't know what consequences that will have. You may call exit handlers that manipulate real world objects that the parent expects to remain intact.
I have the following code that initializes a shared memory containing 1 mutex and 1 condition variable then forks a process where the parent passes to the child some characters through a pipe and signals the child to go an read it.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <pthread.h>
#ifndef _POSIX_THREAD_PROCESS_SHARED
#error This system does not support process shared mutex
#endif
pthread_cond_t *cvptr; //Condition Variable Pointer
pthread_condattr_t cattr; //Condition Variable Attribute
pthread_mutex_t *mptr; //Mutex Pointer
pthread_mutexattr_t matr; //Mutex Attribute
int shared_mem_id; //shared memory Id
int *mp_shared_mem_ptr; //shared memory ptr -- pointing to mutex
int *cv_shared_mem_ptr; //shared memory ptr -- pointing to condition variable
/* Read characters from the pipe and echo them to stdout. */
void read_from_pipe (int file)
{
printf("read_from_pipe()\n");
FILE *stream;
int c;
stream = fdopen (file, "r");
// Lock mutex and then wait for signal to relase mutex
printf("child mutex lock \n");
pthread_mutex_lock( mptr );
printf("child mutex locked\n");
printf("child wait\n");
pthread_cond_wait( cvptr, mptr );
printf("child condition woke up\n");
while ((c = fgetc (stream)) != EOF)
putchar (c);
fclose (stream);
printf("child mutex unlock\n");
pthread_mutex_unlock( mptr );
}
/* Write some random text to the pipe. */
void write_to_pipe (int file)
{
printf("write_to_pipe()\n");
FILE *stream;
stream = fdopen (file, "w");
fprintf (stream, "hello, world!\n");
fprintf (stream, "goodbye, world!\n");
fclose (stream);
pthread_cond_signal( cvptr );
}
int main (void)
{
int rtn;
size_t shm_size;
/* initialize shared memory segment */
shm_size = 1*sizeof(pthread_mutex_t) + 1*sizeof(pthread_cond_t);
if ((shared_mem_id = shmget(IPC_PRIVATE, shm_size, 0660)) < 0)
{
perror("shmget"), exit(1) ;
}
if ((mp_shared_mem_ptr = (int *)shmat(shared_mem_id, (void *)0, 0)) == NULL)
{
perror("shmat"), exit(1);
}
//Offset to find the location of the condition variable in the shared memory
unsigned char* byte_ptr = reinterpret_cast<unsigned char*>(mp_shared_mem_ptr);
byte_ptr += 1*sizeof(pthread_mutex_t);
mptr = (pthread_mutex_t *)mp_shared_mem_ptr;
cvptr = (pthread_cond_t *)byte_ptr;
// Setup Mutex
if (rtn = pthread_mutexattr_init(&matr))
{
fprintf(stderr,"pthreas_mutexattr_init: %s",strerror(rtn)),exit(1);
}
if (rtn = pthread_mutexattr_setpshared(&matr,PTHREAD_PROCESS_SHARED))
{
fprintf(stderr,"pthread_mutexattr_setpshared %s",strerror(rtn)),exit(1);
}
if (rtn = pthread_mutex_init(mptr, &matr))
{
fprintf(stderr,"pthread_mutex_init %s",strerror(rtn)), exit(1);
}
//Setup Condition Variable
if(rtn = pthread_condattr_init(&cattr))
{
fprintf(stderr,"pthread_condattr_init: %s",strerror(rtn)),exit(1);
}
if(pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED))
{
fprintf(stderr,"pthread_condattr_setpshared %s",strerror(rtn)),exit(1);
}
if(pthread_cond_init(cvptr, &cattr))
{
fprintf(stderr,"pthread_cond_init %s",strerror(rtn)),exit(1);
}
pid_t pid;
int mypipe[2];
/* Create the pipe. */
if (pipe (mypipe))
{
fprintf (stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
/* Create the child process. */
pid = fork ();
if (pid == (pid_t) 0)
{
printf ("Child Forked!.\n");
/* This is the child process.
Close other end first. */
close (mypipe[1]);
read_from_pipe (mypipe[0]);
return EXIT_SUCCESS;
}
else if (pid < (pid_t) 0)
{
/* The fork failed. */
fprintf (stderr, "Fork failed.\n");
return EXIT_FAILURE;
}
else
{
printf ("Parent Forked!.\n");
/* This is the parent process.
Close other end first. */
close (mypipe[0]);
write_to_pipe (mypipe[1]);
return EXIT_SUCCESS;
}
}
I think I did something wrong with the initialization of the variables, the code does not core dump but somehow only prints:
Parent Forked!.
write_to_pipe()
Any ideas?
It's possible that write_to_pipe is signalling the condition variable before read_from_pipe reaches the pthread_cond_wait. Condition variables don't do any kind of buffering or counting of signals, so it will simply be lost.