Sono in difficoltà con la creazione del processo e piping l'output del processo secondario in una stringa del processo padre. L'ho fatto funzionare su Windows (usando CreatePipe e CreateProcess e ReadFile), ma non riesco a ottenere l'esatto analogico su Unix per funzionare. Questo è il mio codice:posix_spawnp e piping output figlio a una stringa
#include <spawn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
int exit_code;
int cout_pipe[2];
int cerr_pipe[2];
posix_spawn_file_actions_t action;
if(pipe(cout_pipe) || pipe(cerr_pipe))
cout << "pipe returned an error.\n";
posix_spawn_file_actions_init(&action);
posix_spawn_file_actions_addclose(&action, cout_pipe[0]);
posix_spawn_file_actions_addclose(&action, cerr_pipe[0]);
posix_spawn_file_actions_adddup2(&action, cout_pipe[1], 1);
posix_spawn_file_actions_adddup2(&action, cerr_pipe[1], 2);
posix_spawn_file_actions_addclose(&action, cout_pipe[1]);
posix_spawn_file_actions_addclose(&action, cerr_pipe[1]);
vector<string> argmem = {"bla"};
vector<char*> args = {&argmem[0][0], nullptr}; // I don't want to call new.
pid_t pid;
if(posix_spawnp(&pid, "echo", &action, NULL, &args[0], NULL) != 0)
cout << "posix_spawnp failed with error: " << strerror(errno) << "\n";
//close(cout_pipe[0]);
//close(cerr_pipe[0]);
close(cout_pipe[1]);
close(cerr_pipe[1]);
waitpid(pid,&exit_code,0);
cout << "exit code: " << exit_code << "\n";
// Read from pipes
const size_t buffer_size = 1024;
string buffer;
buffer.resize(buffer_size);
ssize_t bytes_read = read(cout_pipe[0], &buffer[0], buffer_size);
while ((bytes_read = read(cout_pipe[0], &buffer[0], buffer_size)) > 0)
{
cout << "read " << bytes_read << " bytes from stdout.\n";
cout << buffer.substr(0, static_cast<size_t>(bytes_read)+1) << "\n";
bytes_read = read(cout_pipe[0], &buffer[0], buffer_size);
}
if(bytes_read == -1)
cout << "Failure reading from stdout pipe.\n";
while ((bytes_read = read(cerr_pipe[0], &buffer[0], buffer_size)) > 0)
{
cout << "read " << bytes_read << " bytes from stderr.\n";
cout << buffer.substr(0, static_cast<size_t>(bytes_read)+1) << "\n";
bytes_read = read(cout_pipe[0], &buffer[0], buffer_size);
}
if(bytes_read == -1)
cout << "Failure reading from stderr pipe.\n";
posix_spawn_file_actions_destroy(&action);
}
L'output è:
codice di uscita: 0
quindi suppongo che tutto funziona, tranne le tubazioni vero e proprio. Cosa c'è di sbagliato qui? Mi chiedo anche se ci sia un modo per leggere i byte in pipe in un ciclo waitpid, ma quando provo a farlo, il processo genitore si blocca all'infinito.
Non avevo mai sentito parlare di 'posix_spawnp'. Cosa c'è che non va nel buon vecchio 'popen'? Che interessante funzione di syscall/libreria è. Ricorderà questo :) – sehe
'popen' non ha la flessibilità richiesta: AFAICT non riesco a reindirizzare stderr con quello. È anche la funzione più simile all'API di CreateProcess. Heck, MSDN ha anche '_spawnvp' che assomiglia a' posix_spawnp', ma come ho detto, il mio codice 'CreateProcess' sta praticamente funzionando bene. È il lato Unix che al momento non collabora :( – rubenvb
Ho aggiunto il tag C per suscitare interesse Sebbene il codice sia tecnicamente C++, i bit importanti (ovvero il piping e lo spawning) sono puri C. – rubenvb