blob: f3bf71abf235e151e2bd6604086ae157b31ef4b9 [file] [log] [blame]
Mike Dodd8cfa7022010-11-17 11:12:26 -08001/**
2 * @file child_reader.h
3 * Facility for reading from child processes
4 *
5 * @remark Copyright 2002 OProfile authors
6 * @remark Read the file COPYING
7 *
8 * @author Philippe Elie
9 * @author John Levon
10 */
11
12#ifndef CHILD_READER_H
13#define CHILD_READER_H
14
15#include <sys/types.h>
16
17#include <vector>
18#include <string>
19
20/**
21 * a class to read stdout / stderr from a child process.
22 *
23 * two interfaces are provided. read line by line: getline() or read all data
24 * in one : get_data(). In all case get_data() must be called once to flush the
25 * stderr child output
26 */
27/*
28 * FIXME: code review is needed:
29 * - check the getline()/get_data()/block_read() interface.
30 * the expected behavior is:
31 * caller can call getline until nothing is available from the stdout of the
32 * child. in this case child stderr is acumulated in buf2 and can be read
33 * through get_data(). get_data() is blocking until the child close stderr /
34 * stdout (even if the child die by a signal ?). The following corner case must
35 * work but I'm unsure if the code reflect this behavior: the last line of the
36 * child stdout have not necessarilly a LF terminator. the child can output any
37 * size of data in stderr.
38 */
39class child_reader {
40public:
41 /** fork a process. use error() to get error code. Do not try to
42 * use other public member interface if error() return non-zero */
43 child_reader(std::string const & cmd,
44 std::vector<std::string> const & args);
45
46 /** wait for the termination of the child process if this have not
47 * already occur. In this case return code of the child process is not
48 * available. */
49 ~child_reader();
50
51 /** fill result from on line of stdout of the child process.
52 * must be used as:
53 * child_reader reader(...);
54 * while (reader.getline(line)) .... */
55 bool getline(std::string & result);
56
57 /** fill out / err with the stdout / stderr of the child process.
58 * You can call this after calling one or more time getline(...). This
59 * call is blocking until the child die and so on all subsequent
60 * call will fail */
61 bool get_data(std::ostream & out, std::ostream & err);
62
63 /** rather to rely on dtor to wait for the termination of the child you
64 * can use terminate_process() to get the return code of the child
65 * process */
66 int terminate_process();
67
68 /** return the status of the first error encoutered
69 * != 0 : something feel wrong, use error_str() to get an error
70 * message */
71 int error() const { return first_error; }
72
73 /**
74 * return an error message if appropriate, if the process has
75 * been successfully exec'ed and is not terminate the error message
76 * is always empty. Error message is also empty if the child process
77 * terminate successfully. Else three type of error message exist:
78 * - "unable to fork" followed by sterror(errno)
79 * - "process_name return xxx" xxx is return code
80 * - "process_name terminated by signal xxx" xxx is signal number
81 */
82 std::string error_str() const;
83
84private:
85 // ctor helper: create the child process.
86 void exec_command(std::string const & cmd,
87 std::vector<std::string> const & args);
88 // return false when eof condition is reached on fd1. fd2 can have
89 // already input in the pipe buffer or in buf2.
90 bool block_read();
91
92 int fd1;
93 int fd2;
94 ssize_t pos1;
95 ssize_t end1;
96 ssize_t pos2;
97 ssize_t end2;
98 pid_t pid;
99 int first_error;
100 // child stderr is handled especially, we need to retain data even
101 // if caller read only stdout of the child.
102 char * buf2;
103 ssize_t sz_buf2;
104 char * buf1;
105 std::string process_name;
106 bool is_terminated;
107 bool terminate_on_exception;
108 bool forked;
109};
110
111#endif // CHILD_READER_H