mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 16:52:43 +00:00 
			
		
		
		
	Kernel: Report EAGAIN from read() on a non-blocking socket if the buffer is empty
This is not EOF, and never should have been so -- can trip up other code when porting. Also updates LibGUI and WindowServer which both relied on the old behaviour (and didn't work without changes). There may be others, but I didn't run into them with a quick inspection.
This commit is contained in:
		
							parent
							
								
									40a5eb4e6e
								
							
						
					
					
						commit
						a8864dc590
					
				
					 3 changed files with 20 additions and 11 deletions
				
			
		|  | @ -153,10 +153,20 @@ bool LocalSocket::can_read(FileDescriptor& descriptor) const | ||||||
| ssize_t LocalSocket::read(FileDescriptor& descriptor, byte* buffer, ssize_t size) | ssize_t LocalSocket::read(FileDescriptor& descriptor, byte* buffer, ssize_t size) | ||||||
| { | { | ||||||
|     auto role = descriptor.socket_role(); |     auto role = descriptor.socket_role(); | ||||||
|     if (role == SocketRole::Accepted) |     if (role == SocketRole::Accepted) { | ||||||
|  |         if (!descriptor.is_blocking()) { | ||||||
|  |             if (m_for_server.is_empty()) | ||||||
|  |                 return -EAGAIN; | ||||||
|  |         } | ||||||
|         return m_for_server.read(buffer, size); |         return m_for_server.read(buffer, size); | ||||||
|     if (role == SocketRole::Connected) |     } | ||||||
|  |     if (role == SocketRole::Connected) { | ||||||
|  |         if (!descriptor.is_blocking()) { | ||||||
|  |             if (m_for_client.is_empty()) | ||||||
|  |                 return -EAGAIN; | ||||||
|  |         } | ||||||
|         return m_for_client.read(buffer, size); |         return m_for_client.read(buffer, size); | ||||||
|  |     } | ||||||
|     ASSERT_NOT_REACHED(); |     ASSERT_NOT_REACHED(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -324,22 +324,22 @@ void GEventLoop::process_unprocessed_bundles() | ||||||
| 
 | 
 | ||||||
| bool GEventLoop::drain_messages_from_server() | bool GEventLoop::drain_messages_from_server() | ||||||
| { | { | ||||||
|     bool is_first_pass = true; |  | ||||||
|     for (;;) { |     for (;;) { | ||||||
|         WSAPI_ServerMessage message; |         WSAPI_ServerMessage message; | ||||||
|         ssize_t nread = read(s_windowserver_fd, &message, sizeof(WSAPI_ServerMessage)); |         ssize_t nread = read(s_windowserver_fd, &message, sizeof(WSAPI_ServerMessage)); | ||||||
|         if (nread < 0) { |         if (nread < 0) { | ||||||
|  |             if (errno == EAGAIN) { | ||||||
|  |                 return true; | ||||||
|  |             } | ||||||
|             perror("read"); |             perror("read"); | ||||||
|             quit(1); |             quit(1); | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|         if (nread == 0) { |         if (nread == 0) { | ||||||
|             if (is_first_pass) { |             fprintf(stderr, "EOF on WindowServer fd\n"); | ||||||
|                 fprintf(stderr, "EOF on WindowServer fd\n"); |             quit(1); | ||||||
|                 quit(1); |             exit(-1); | ||||||
|                 return false; |             return false; | ||||||
|             } |  | ||||||
|             return true; |  | ||||||
|         } |         } | ||||||
|         assert(nread == sizeof(message)); |         assert(nread == sizeof(message)); | ||||||
|         ByteBuffer extra_data; |         ByteBuffer extra_data; | ||||||
|  | @ -355,7 +355,6 @@ bool GEventLoop::drain_messages_from_server() | ||||||
|             ASSERT(extra_nread == message.extra_size); |             ASSERT(extra_nread == message.extra_size); | ||||||
|         } |         } | ||||||
|         m_unprocessed_bundles.append({ move(message), move(extra_data) }); |         m_unprocessed_bundles.append({ move(message), move(extra_data) }); | ||||||
|         is_first_pass = false; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -301,7 +301,7 @@ void WSEventLoop::drain_client(WSClientConnection& client) | ||||||
|         WSAPI_ClientMessage message; |         WSAPI_ClientMessage message; | ||||||
|         // FIXME: Don't go one message at a time, that's so much context switching, oof.
 |         // FIXME: Don't go one message at a time, that's so much context switching, oof.
 | ||||||
|         ssize_t nread = read(client.fd(), &message, sizeof(WSAPI_ClientMessage)); |         ssize_t nread = read(client.fd(), &message, sizeof(WSAPI_ClientMessage)); | ||||||
|         if (nread == 0) { |         if (nread == 0 || (nread == -1 && errno == EAGAIN)) { | ||||||
|             if (!messages_received) |             if (!messages_received) | ||||||
|                 post_event(client, make<WSClientDisconnectedNotification>(client.client_id())); |                 post_event(client, make<WSClientDisconnectedNotification>(client.client_id())); | ||||||
|             break; |             break; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Robin Burchell
						Robin Burchell