Mam problemy z tworzeniem procesów i wyprowadzaniem wyniku procesu potomnego do ciągu procesu nadrzędnego. Zrobiłem to działając na Windowsie (używając CreatePipe i CreateProcess i ReadFile), ale nie mogę uzyskać dokładnego analogu na Unix. To jest mój kod:posix_spawnp i wyprowadzanie potomne potoków do łańcucha znaków
#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);
}
Wyjście jest:
kod wyjścia: 0
Więc przypuszczam, wszystko działa oprócz rzeczywistej rurociągów. Co jest nie tak? Zastanawiam się również, czy istnieje sposób na odczytanie bajtów piped w pętli waitpid, ale kiedy próbuję tego, proces nadrzędny zawiesza się w nieskończoność.
Nigdy nie słyszałem o "posix_spawnp". Co jest nie tak z dobrym starym 'popen'? Co to jest interesująca funkcja syscall/library. Zapamięta to :) – sehe
'popen' nie ma wymaganej elastyczności: AFAICT Nie mogę przekierować stderr z tym. Jest to również funkcja, która najbardziej przypomina API 'CreateProcess'. Heck, MSDN ma nawet '_spawnvp', który przypomina' posix_spawnp', ale jak już powiedziałem, mój kod 'CreateProcess' w zasadzie działa dobrze. Jest to strona Unixa, która aktualnie nie współpracuje :( – rubenvb
Dodałem tag C, aby wzbudzić zainteresowanie.Chociaż kod jest technicznie C++, ważne bity (np. Piping i spawning) są czyste C. – rubenvb