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) | ||||
| { | ||||
|     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); | ||||
|     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); | ||||
|     } | ||||
|     ASSERT_NOT_REACHED(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -324,22 +324,22 @@ void GEventLoop::process_unprocessed_bundles() | |||
| 
 | ||||
| bool GEventLoop::drain_messages_from_server() | ||||
| { | ||||
|     bool is_first_pass = true; | ||||
|     for (;;) { | ||||
|         WSAPI_ServerMessage message; | ||||
|         ssize_t nread = read(s_windowserver_fd, &message, sizeof(WSAPI_ServerMessage)); | ||||
|         if (nread < 0) { | ||||
|             if (errno == EAGAIN) { | ||||
|                 return true; | ||||
|             } | ||||
|             perror("read"); | ||||
|             quit(1); | ||||
|             return false; | ||||
|         } | ||||
|         if (nread == 0) { | ||||
|             if (is_first_pass) { | ||||
|                 fprintf(stderr, "EOF on WindowServer fd\n"); | ||||
|                 quit(1); | ||||
|                 return false; | ||||
|             } | ||||
|             return true; | ||||
|             fprintf(stderr, "EOF on WindowServer fd\n"); | ||||
|             quit(1); | ||||
|             exit(-1); | ||||
|             return false; | ||||
|         } | ||||
|         assert(nread == sizeof(message)); | ||||
|         ByteBuffer extra_data; | ||||
|  | @ -355,7 +355,6 @@ bool GEventLoop::drain_messages_from_server() | |||
|             ASSERT(extra_nread == message.extra_size); | ||||
|         } | ||||
|         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; | ||||
|         // 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)); | ||||
|         if (nread == 0) { | ||||
|         if (nread == 0 || (nread == -1 && errno == EAGAIN)) { | ||||
|             if (!messages_received) | ||||
|                 post_event(client, make<WSClientDisconnectedNotification>(client.client_id())); | ||||
|             break; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Robin Burchell
						Robin Burchell