xref: /aosp_15_r20/external/google-breakpad/src/common/linux/scoped_pipe.h (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1*9712c20fSFrederick Mayle // Copyright 2022 Google LLC
2*9712c20fSFrederick Mayle //
3*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without
4*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are
5*9712c20fSFrederick Mayle // met:
6*9712c20fSFrederick Mayle //
7*9712c20fSFrederick Mayle //     * Redistributions of source code must retain the above copyright
8*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer.
9*9712c20fSFrederick Mayle //     * Redistributions in binary form must reproduce the above
10*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer
11*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the
12*9712c20fSFrederick Mayle // distribution.
13*9712c20fSFrederick Mayle //     * Neither the name of Google LLC nor the names of its
14*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from
15*9712c20fSFrederick Mayle // this software without specific prior written permission.
16*9712c20fSFrederick Mayle //
17*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*9712c20fSFrederick Mayle 
29*9712c20fSFrederick Mayle #ifndef COMMON_LINUX_SCOPED_PIPE_H_
30*9712c20fSFrederick Mayle #define COMMON_LINUX_SCOPED_PIPE_H_
31*9712c20fSFrederick Mayle 
32*9712c20fSFrederick Mayle #include <stdint.h>
33*9712c20fSFrederick Mayle #include <string>
34*9712c20fSFrederick Mayle 
35*9712c20fSFrederick Mayle namespace google_breakpad {
36*9712c20fSFrederick Mayle 
37*9712c20fSFrederick Mayle // Small RAII wrapper for a pipe pair.
38*9712c20fSFrederick Mayle //
39*9712c20fSFrederick Mayle // Example (both ends of pipe in same process):
40*9712c20fSFrederick Mayle //   ScopedPipe tmp;
41*9712c20fSFrederick Mayle //   std::string line;
42*9712c20fSFrederick Mayle //   if (tmp.Init() && tmp.Write(bytes, bytes_len)) {
43*9712c20fSFrederick Mayle //     tmp.CloseWriteFd();
44*9712c20fSFrederick Mayle //     while (tmp.ReadLine(&line)) {
45*9712c20fSFrederick Mayle //       std::cerr << line << std::endl;
46*9712c20fSFrederick Mayle //     }
47*9712c20fSFrederick Mayle //   }
48*9712c20fSFrederick Mayle //
49*9712c20fSFrederick Mayle // Example (reading output from a child process):
50*9712c20fSFrederick Mayle //   ScopedPipe tmp;
51*9712c20fSFrederick Mayle //   if (fork()) {
52*9712c20fSFrederick Mayle //     // Parent process, read from the read end of the pipe.
53*9712c20fSFrederick Mayle //     std::string line;
54*9712c20fSFrederick Mayle //     while (tmp.ReadLine(line)) {
55*9712c20fSFrederick Mayle //       // Process output...
56*9712c20fSFrederick Mayle //     }
57*9712c20fSFrederick Mayle //     // Close read pipe once done processing the output that we wanted, this
58*9712c20fSFrederick Mayle //     // should ensure that the child process exits even if we didn't read all
59*9712c20fSFrederick Mayle //     // of the output.
60*9712c20fSFrederick Mayle //     tmp.CloseReadFd();
61*9712c20fSFrederick Mayle //     // Parent process should handle waiting for child to exit here...
62*9712c20fSFrederick Mayle //   } else {
63*9712c20fSFrederick Mayle //     // Child process, close the read fd and dup the write fd before exec'ing.
64*9712c20fSFrederick Mayle //     tmp.CloseReadFd();
65*9712c20fSFrederick Mayle //     tmp.Dup2WriteFd(STDOUT_FILENO);
66*9712c20fSFrederick Mayle //     tmp.Dup2WriteFd(STDERR_FILENO);
67*9712c20fSFrederick Mayle //     execl("some-command", "some-arguments");
68*9712c20fSFrederick Mayle //   }
69*9712c20fSFrederick Mayle class ScopedPipe {
70*9712c20fSFrederick Mayle  public:
71*9712c20fSFrederick Mayle   ScopedPipe();
72*9712c20fSFrederick Mayle   ~ScopedPipe();
73*9712c20fSFrederick Mayle 
74*9712c20fSFrederick Mayle   // Creates the pipe pair - returns false on error.
75*9712c20fSFrederick Mayle   bool Init();
76*9712c20fSFrederick Mayle 
77*9712c20fSFrederick Mayle   // Close the read pipe. This only needs to be used when the read pipe needs to
78*9712c20fSFrederick Mayle   // be closed earlier.
79*9712c20fSFrederick Mayle   void CloseReadFd();
80*9712c20fSFrederick Mayle 
81*9712c20fSFrederick Mayle   // Close the write pipe. This only needs to be used when the write pipe needs
82*9712c20fSFrederick Mayle   // to be closed earlier.
83*9712c20fSFrederick Mayle   void CloseWriteFd();
84*9712c20fSFrederick Mayle 
85*9712c20fSFrederick Mayle   // Reads characters until newline or end of pipe. On read failure this will
86*9712c20fSFrederick Mayle   // close the read pipe, but continue to return true and read buffered lines
87*9712c20fSFrederick Mayle   // until the internal buffering is exhausted. This will block if there is no
88*9712c20fSFrederick Mayle   // data available on the read pipe.
89*9712c20fSFrederick Mayle   bool ReadLine(std::string& line);
90*9712c20fSFrederick Mayle 
91*9712c20fSFrederick Mayle   // Writes bytes to the write end of the pipe, returns false and closes write
92*9712c20fSFrederick Mayle   // pipe on failure.
93*9712c20fSFrederick Mayle   bool WriteForTesting(const void* bytes, size_t bytes_len);
94*9712c20fSFrederick Mayle 
95*9712c20fSFrederick Mayle   // Calls the dup2 system call to replace any existing open file descriptor
96*9712c20fSFrederick Mayle   // with number new_fd with a copy of the current write end file descriptor
97*9712c20fSFrederick Mayle   // for the pipe.
98*9712c20fSFrederick Mayle   int Dup2WriteFd(int new_fd) const;
99*9712c20fSFrederick Mayle 
100*9712c20fSFrederick Mayle  private:
GetReadFd()101*9712c20fSFrederick Mayle   int GetReadFd() const {
102*9712c20fSFrederick Mayle     return fds_[0];
103*9712c20fSFrederick Mayle   }
104*9712c20fSFrederick Mayle 
GetWriteFd()105*9712c20fSFrederick Mayle   int GetWriteFd() const {
106*9712c20fSFrederick Mayle     return fds_[1];
107*9712c20fSFrederick Mayle   }
108*9712c20fSFrederick Mayle 
109*9712c20fSFrederick Mayle   int fds_[2];
110*9712c20fSFrederick Mayle   std::string read_buffer_;
111*9712c20fSFrederick Mayle };
112*9712c20fSFrederick Mayle 
113*9712c20fSFrederick Mayle }  // namespace google_breakpad
114*9712c20fSFrederick Mayle 
115*9712c20fSFrederick Mayle #endif // COMMON_LINUX_SCOPED_PIPE_H_
116