@@ -47,36 +47,40 @@ static _Noreturn void handle_vchan_error(const char *op)
4747 * don't care, because we created it)
4848 */
4949
50- static void close_stdin (int fd , bool restore_block ) {
50+ static void close_stdin (int fd , bool restore_block , bool close_fd ) {
5151 if (fd == -1 )
5252 return ;
5353
5454 if (restore_block )
5555 set_block (fd );
5656
5757 if (fd == 1 ) {
58- close (fd );
59- } else if (shutdown (fd , SHUT_WR ) == -1 ) {
60- if (errno == ENOTSOCK )
58+ if (close_fd )
6159 close (fd );
62- else
60+ } else if (shutdown (fd , SHUT_WR ) == -1 ) {
61+ if (errno == ENOTSOCK ) {
62+ if (close_fd )
63+ close (fd );
64+ } else
6365 PERROR ("shutdown close_stdin" );
6466 }
6567}
6668
67- static void close_stdout (int fd , bool restore_block ) {
69+ static void close_stdout (int fd , bool restore_block , bool close_fd ) {
6870 if (fd == -1 )
6971 return ;
7072
7173 if (restore_block )
7274 set_block (fd );
7375
7476 if (fd == 0 ) {
75- close (fd );
76- } else if (shutdown (fd , SHUT_RD ) == -1 ) {
77- if (errno == ENOTSOCK )
77+ if (close_fd )
7878 close (fd );
79- else
79+ } else if (shutdown (fd , SHUT_RD ) == -1 ) {
80+ if (errno == ENOTSOCK ) {
81+ if (close_fd )
82+ close (fd );
83+ } else
8084 PERROR ("shutdown close_stdout" );
8185 }
8286}
@@ -117,7 +121,7 @@ int process_io(const struct process_io_request *req) {
117121 pid_t local_status = -1 ;
118122 pid_t remote_status = -1 ;
119123 int stdout_msg_type = is_service ? MSG_DATA_STDOUT : MSG_DATA_STDIN ;
120- bool use_stdio_socket = false ;
124+ bool use_stdio_socket = stdin_fd == stdout_fd ;
121125
122126 int ret ;
123127 struct pollfd fds [FD_NUM ];
@@ -134,8 +138,6 @@ int process_io(const struct process_io_request *req) {
134138 set_nonblock (stdin_fd );
135139 if (stdout_fd != stdin_fd )
136140 set_nonblock (stdout_fd );
137- else if ((stdout_fd = fcntl (stdin_fd , F_DUPFD_CLOEXEC , 3 )) < 0 )
138- abort (); // not worth handling running out of file descriptors
139141 if (stderr_fd >= 0 )
140142 set_nonblock (stderr_fd );
141143
@@ -149,7 +151,7 @@ int process_io(const struct process_io_request *req) {
149151 else
150152 local_status = WEXITSTATUS (status );
151153 if (stdin_fd >= 0 ) {
152- close_stdin (stdin_fd , !use_stdio_socket );
154+ close_stdin (stdin_fd , !use_stdio_socket , stdin_fd != stdout_fd );
153155 stdin_fd = -1 ;
154156 }
155157 }
@@ -194,14 +196,12 @@ int process_io(const struct process_io_request *req) {
194196 }
195197
196198 /* child signaled desire to use single socket for both stdin and stdout */
197- if (sigusr1 && * sigusr1 ) {
199+ if (sigusr1 && * sigusr1 && stdin_fd != stdout_fd ) {
198200 if (stdout_fd != -1 ) {
199- do
200- errno = 0 ;
201- while (dup3 (stdin_fd , stdout_fd , O_CLOEXEC ) &&
202- (errno == EINTR || errno == EBUSY ));
203- // other errors are fatal
204- if (errno ) {
201+ while (dup3 (stdin_fd , stdout_fd , O_CLOEXEC ) == -1 ) {
202+ if (errno == EINTR || errno == EBUSY )
203+ continue ;
204+ // other errors are fatal
205205 PERROR ("dup3" );
206206 abort ();
207207 }
@@ -265,7 +265,7 @@ int process_io(const struct process_io_request *req) {
265265 handle_vchan_error ("wait" );
266266
267267 if (stdin_fd >= 0 && fds [FD_STDIN ].revents & (POLLHUP | POLLERR )) {
268- close_stdin (stdin_fd , !use_stdio_socket );
268+ close_stdin (stdin_fd , !use_stdio_socket , stdin_fd != stdout_fd );
269269 stdin_fd = -1 ;
270270 }
271271
@@ -282,15 +282,15 @@ int process_io(const struct process_io_request *req) {
282282 handle_vchan_error ("read" );
283283 break ;
284284 case REMOTE_EOF :
285- close_stdin (stdin_fd , !use_stdio_socket );
285+ close_stdin (stdin_fd , !use_stdio_socket , stdin_fd != stdout_fd );
286286 stdin_fd = -1 ;
287287 break ;
288288 case REMOTE_EXITED :
289289 /* Remote process exited, we don't need any more data from
290290 * local FDs. However, don't exit yet, because there might
291291 * still be some data in stdin_buf waiting to be flushed.
292292 */
293- close_stdout (stdout_fd , !use_stdio_socket );
293+ close_stdout (stdout_fd , !use_stdio_socket , stdin_fd != stdout_fd );
294294 stdout_fd = -1 ;
295295 close_stderr (stderr_fd );
296296 stderr_fd = -1 ;
@@ -304,7 +304,7 @@ int process_io(const struct process_io_request *req) {
304304 handle_vchan_error ("send(handle_input stdout)" );
305305 break ;
306306 case REMOTE_EOF :
307- close_stdout (stdout_fd , !use_stdio_socket );
307+ close_stdout (stdout_fd , !use_stdio_socket , stdin_fd != stdout_fd );
308308 stdout_fd = -1 ;
309309 break ;
310310 }
@@ -325,8 +325,8 @@ int process_io(const struct process_io_request *req) {
325325 }
326326 /* make sure that all the pipes/sockets are closed, so the child process
327327 * (if any) will know that the connection is terminated */
328- close_stdin (stdin_fd , true);
329- close_stdout (stdout_fd , true);
328+ close_stdin (stdin_fd , true, stdin_fd != stdout_fd );
329+ close_stdout (stdout_fd , true, true );
330330 close_stderr (stderr_fd );
331331
332332 /* wait for local process, in case we exited early */
0 commit comments