@@ -45,6 +45,25 @@ namespace subprocess {
4545 message += std::strerror (errno_code);
4646 throw OSError (message);
4747 }
48+ struct NoSigPipe {
49+ #ifndef _WIN32
50+ NoSigPipe () {
51+ // get the current state
52+ sigprocmask (SIG_BLOCK , NULL , &old_state);
53+
54+ sigset_t set = old_state;
55+ sigaddset (&set, SIGPIPE );
56+ sigprocmask (SIG_BLOCK , &set, NULL );
57+ }
58+
59+ ~NoSigPipe () {
60+ sigprocmask (SIG_BLOCK , &old_state, NULL );
61+ }
62+
63+ private:
64+ sigset_t old_state;
65+ #endif
66+ };
4867 }
4968 double monotonic_seconds () {
5069 static bool needs_init = true ;
@@ -91,6 +110,7 @@ namespace subprocess {
91110 };
92111 std::thread pipe_thread (PipeHandle input, std::ostream* output) {
93112 return std::thread ([=]() {
113+ details::NoSigPipe noSigPipe;
94114 AutoClosePipe autoclose (input);
95115 std::vector<char > buffer (2048 );
96116 while (true ) {
@@ -102,58 +122,83 @@ namespace subprocess {
102122 });
103123 }
104124
125+ [[nodiscard]]
126+ static ssize_t fwrite_fully (FILE * output, const void * buffer, size_t size) {
127+ const uint8_t * cursor = reinterpret_cast <const uint8_t *>(buffer);
128+ ssize_t total = 0 ;
129+ while (total < size) {
130+ auto transferred = fwrite (cursor, 1 , size - total, output);
131+ if (transferred == 0 )
132+ break ;
133+ cursor += transferred;
134+ total += transferred;
135+ }
136+ return total;
137+ }
138+
105139 std::thread pipe_thread (PipeHandle input, FILE * output) {
106140 return std::thread ([=]() {
141+ details::NoSigPipe noSigPipe;
107142 AutoClosePipe autoclose (input);
108143 std::vector<char > buffer (2048 );
109144 while (true ) {
110- ssize_t transfered = pipe_read (input, &buffer[0 ], buffer.size ());
111- if (transfered <= 0 )
145+ ssize_t transferred = pipe_read (input, &buffer[0 ], buffer.size ());
146+ if (transferred <= 0 )
147+ break ;
148+ transferred = fwrite_fully (output, &buffer[0 ], transferred);
149+ if (transferred <= 0 )
112150 break ;
113- fwrite (&buffer[0 ], 1 , transfered, output);
114151 }
115152 });
116153 }
154+
117155 std::thread pipe_thread (FILE * input, PipeHandle output) {
118156 return std::thread ([=]() {
157+ details::NoSigPipe noSigPipe;
119158 AutoClosePipe autoclose (output);
120159 std::vector<char > buffer (2048 );
121160 while (true ) {
122- ssize_t transfered = fread (&buffer[0 ], 1 , buffer.size (), input);
123- if (transfered <= 0 )
161+ ssize_t transferred = fread (&buffer[0 ], 1 , buffer.size (), input);
162+ if (transferred <= 0 )
163+ break ;
164+ transferred = pipe_write_fully (output, &buffer[0 ], transferred);
165+ if (transferred <= 0 )
124166 break ;
125- pipe_write (output, &buffer[0 ], transfered);
126167 }
127168 });
128169 }
129170 std::thread pipe_thread (std::string& input, PipeHandle output) {
130171 return std::thread ([input (move (input)), output]() {
172+ details::NoSigPipe noSigPipe;
131173 AutoClosePipe autoclose (output);
132174
133175 std::size_t pos = 0 ;
134176 while (pos < input.size ()) {
135- ssize_t transfered = pipe_write (output, input.c_str ()+pos, input.size () - pos);
136- if (transfered <= 0 )
177+ ssize_t transferred = pipe_write_fully (output, input.c_str ()+pos, input.size () - pos);
178+ if (transferred <= 0 )
137179 break ;
138- pos += transfered ;
180+ pos += transferred ;
139181 }
140182 });
141183 }
142184 std::thread pipe_thread (std::istream* input, PipeHandle output) {
143185 return std::thread ([=]() {
186+ details::NoSigPipe noSigPipe;
144187 AutoClosePipe autoclose (output);
145188 std::vector<char > buffer (2048 );
146189 while (true ) {
147190 input->read (&buffer[0 ], buffer.size ());
148- ssize_t transfered = input->gcount ();
191+ ssize_t transferred = input->gcount ();
149192 if (input->bad ())
150193 break ;
151- if (transfered <= 0 ) {
194+ if (transferred <= 0 ) {
152195 if (input->eof ())
153196 break ;
154197 continue ;
155198 }
156- pipe_write (output, &buffer[0 ], transfered);
199+ transferred = pipe_write_fully (output, &buffer[0 ], transferred);
200+ if (transferred <= 0 )
201+ break ;
157202 }
158203 });
159204 }
@@ -279,6 +324,7 @@ namespace subprocess {
279324 Popen::~Popen () {
280325 close ();
281326 }
327+
282328 void Popen::close () {
283329 if (cin_thread.joinable ())
284330 cin_thread.join ();
0 commit comments