• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
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  */
39 class child_reader {
40 public:
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 */
error()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 
84 private:
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
112