Thanks, Feng Li
Dima Stepanov <dimas...@yandex-team.ru> 于2020年4月30日周四 下午9:36写道: > > During testing of the vhost-user-blk reconnect functionality the qemu > SIGSEGV was triggered: > start qemu as: > x86_64-softmmu/qemu-system-x86_64 -m 1024M -M q35 \ > -object > memory-backend-file,id=ram-node0,size=1024M,mem-path=/dev/shm/qemu,share=on \ > -numa node,cpus=0,memdev=ram-node0 \ > -chardev socket,id=chardev0,path=./vhost.sock,noserver,reconnect=1 \ > -device vhost-user-blk-pci,chardev=chardev0,num-queues=4 --enable-kvm > start vhost-user-blk daemon: > ./vhost-user-blk -s ./vhost.sock -b test-img.raw > > If vhost-user-blk will be killed during the vhost initialization > process, for instance after getting VHOST_SET_VRING_CALL command, then > QEMU will fail with the following backtrace: > > Thread 1 "qemu-system-x86" received signal SIGSEGV, Segmentation fault. > 0x00005555559272bb in vhost_user_read (dev=0x7fffef2d53e0, msg=0x7fffffffd5b0) > at ./hw/virtio/vhost-user.c:260 > 260 CharBackend *chr = u->user->chr; > > #0 0x00005555559272bb in vhost_user_read (dev=0x7fffef2d53e0, > msg=0x7fffffffd5b0) > at ./hw/virtio/vhost-user.c:260 > #1 0x000055555592acb8 in vhost_user_get_config (dev=0x7fffef2d53e0, > config=0x7fffef2d5394 "", config_len=60) > at ./hw/virtio/vhost-user.c:1645 > #2 0x0000555555925525 in vhost_dev_get_config (hdev=0x7fffef2d53e0, > config=0x7fffef2d5394 "", config_len=60) > at ./hw/virtio/vhost.c:1490 > #3 0x00005555558cc46b in vhost_user_blk_device_realize (dev=0x7fffef2d51a0, > errp=0x7fffffffd8f0) > at ./hw/block/vhost-user-blk.c:429 > #4 0x0000555555920090 in virtio_device_realize (dev=0x7fffef2d51a0, > errp=0x7fffffffd948) > at ./hw/virtio/virtio.c:3615 > #5 0x0000555555a9779c in device_set_realized (obj=0x7fffef2d51a0, > value=true, errp=0x7fffffffdb88) > at ./hw/core/qdev.c:891 > ... > > The problem is that vhost_user_write doesn't get an error after > disconnect and try to call vhost_user_read(). The tcp_chr_write() > routine should return -1 in case of disconnect. Indicate the EIO error > if this routine is called in the disconnected state. > > Signed-off-by: Dima Stepanov <dimas...@yandex-team.ru> > --- > chardev/char-socket.c | 8 +++++--- > 1 file changed, 5 insertions(+), 3 deletions(-) > > diff --git a/chardev/char-socket.c b/chardev/char-socket.c > index 185fe38..c128cca 100644 > --- a/chardev/char-socket.c > +++ b/chardev/char-socket.c > @@ -175,14 +175,16 @@ static int tcp_chr_write(Chardev *chr, const uint8_t > *buf, int len) > if (ret < 0 && errno != EAGAIN) { > if (tcp_chr_read_poll(chr) <= 0) { > tcp_chr_disconnect_locked(chr); > - return len; > + /* Return an error since we made a disconnect. */ > + return ret; The `return` statement could be deleted. The outside has a return statement. > } /* else let the read handler finish it properly */ > } > > return ret; > } else { > - /* XXX: indicate an error ? */ > - return len; > + /* Indicate an error. */ > + errno = EIO; > + return -1; > } > } > > -- > 2.7.4 >