xwrite: poll on non-blocking FDs
write(2) can hit the same EAGAIN/EWOULDBLOCK errors as read(2),
so busy-looping on a non-blocking FD is a waste of resources.
Currently, I do not know of a way for this happen:
* the NonBlocking directive in systemd does not apply to stdin,
  stdout, or stderr.
* xinetd provides no way to set the non-blocking flag at all
But theoretically, it's possible a careless C10K HTTP server
could use pipe2(..., O_NONBLOCK) to setup a pipe for
git-http-backend with only the intent to use non-blocking reads;
but accidentally leave non-blocking set on the write end passed
as stdout to git-upload-pack.
Followup-to: 1079c4be0b ("xread: poll on non blocking fds")
Signed-off-by: Eric Wong <e@80x24.org>
Reviewed-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
			
			
				maint
			
			
		
							parent
							
								
									c22f620205
								
							
						
					
					
						commit
						ef1cf0167a
					
				
							
								
								
									
										22
									
								
								wrapper.c
								
								
								
								
							
							
						
						
									
										22
									
								
								wrapper.c
								
								
								
								
							|  | @ -271,8 +271,26 @@ ssize_t xwrite(int fd, const void *buf, size_t len) | ||||||
| 	    len = MAX_IO_SIZE; | 	    len = MAX_IO_SIZE; | ||||||
| 	while (1) { | 	while (1) { | ||||||
| 		nr = write(fd, buf, len); | 		nr = write(fd, buf, len); | ||||||
| 		if ((nr < 0) && (errno == EAGAIN || errno == EINTR)) | 		if (nr < 0) { | ||||||
| 			continue; | 			if (errno == EINTR) | ||||||
|  | 				continue; | ||||||
|  | 			if (errno == EAGAIN || errno == EWOULDBLOCK) { | ||||||
|  | 				struct pollfd pfd; | ||||||
|  | 				pfd.events = POLLOUT; | ||||||
|  | 				pfd.fd = fd; | ||||||
|  | 				/* | ||||||
|  | 				 * it is OK if this poll() failed; we | ||||||
|  | 				 * want to leave this infinite loop | ||||||
|  | 				 * only when write() returns with | ||||||
|  | 				 * success, or an expected failure, | ||||||
|  | 				 * which would be checked by the next | ||||||
|  | 				 * call to write(2). | ||||||
|  | 				 */ | ||||||
|  | 				poll(&pfd, 1, -1); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		return nr; | 		return nr; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Eric Wong
						Eric Wong