qemu-char: Keep pty slave file descriptor open until the master is closed
If a process opens the slave pts device, writes data to it, then immediately closes it, the data doesn't reliably get delivered to the emulated serial port. This seems to be because a read of the master pty device returns EIO on Linux if no process has the pts device open, even when data is waiting "in the pipe". A fix seems to be for QEMU to keep the pts file descriptor open until the pty is closed, as per the below patch. Signed-off-by: Ashley Jonathan <jonathan.ashley@altran.com> Message-Id: <AC19797808C8D548ABDE0CA4A97AA30A30DEB409@XMB-DCFR-37.europe.corp.altran.com> Reviewed-by: Michael Tokarev <mjt@tls.msk.ru> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									5b82b703b6
								
							
						
					
					
						commit
						34689e206a
					
				@ -1171,6 +1171,7 @@ typedef struct {
 | 
				
			|||||||
    int connected;
 | 
					    int connected;
 | 
				
			||||||
    guint timer_tag;
 | 
					    guint timer_tag;
 | 
				
			||||||
    guint open_tag;
 | 
					    guint open_tag;
 | 
				
			||||||
 | 
					    int slave_fd;
 | 
				
			||||||
} PtyCharDriver;
 | 
					} PtyCharDriver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void pty_chr_update_read_handler_locked(CharDriverState *chr);
 | 
					static void pty_chr_update_read_handler_locked(CharDriverState *chr);
 | 
				
			||||||
@ -1347,6 +1348,7 @@ static void pty_chr_close(struct CharDriverState *chr)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    qemu_mutex_lock(&chr->chr_write_lock);
 | 
					    qemu_mutex_lock(&chr->chr_write_lock);
 | 
				
			||||||
    pty_chr_state(chr, 0);
 | 
					    pty_chr_state(chr, 0);
 | 
				
			||||||
 | 
					    close(s->slave_fd);
 | 
				
			||||||
    object_unref(OBJECT(s->ioc));
 | 
					    object_unref(OBJECT(s->ioc));
 | 
				
			||||||
    if (s->timer_tag) {
 | 
					    if (s->timer_tag) {
 | 
				
			||||||
        g_source_remove(s->timer_tag);
 | 
					        g_source_remove(s->timer_tag);
 | 
				
			||||||
@ -1374,7 +1376,6 @@ static CharDriverState *qemu_chr_open_pty(const char *id,
 | 
				
			|||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    close(slave_fd);
 | 
					 | 
				
			||||||
    qemu_set_nonblock(master_fd);
 | 
					    qemu_set_nonblock(master_fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    chr = qemu_chr_alloc(common, errp);
 | 
					    chr = qemu_chr_alloc(common, errp);
 | 
				
			||||||
@ -1399,6 +1400,7 @@ static CharDriverState *qemu_chr_open_pty(const char *id,
 | 
				
			|||||||
    chr->explicit_be_open = true;
 | 
					    chr->explicit_be_open = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->ioc = QIO_CHANNEL(qio_channel_file_new_fd(master_fd));
 | 
					    s->ioc = QIO_CHANNEL(qio_channel_file_new_fd(master_fd));
 | 
				
			||||||
 | 
					    s->slave_fd = slave_fd;
 | 
				
			||||||
    s->timer_tag = 0;
 | 
					    s->timer_tag = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return chr;
 | 
					    return chr;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user