From: Oliver Kurth Date: Wed, 1 Apr 2020 18:31:37 +0000 (-0700) Subject: Add a retry loop to VSockChannelStart() to recover on start failure. X-Git-Tag: stable-11.2.0~261 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6fcc7bdd696cec8f04c748d3807bbce4dd3230b5;p=thirdparty%2Fopen-vm-tools.git Add a retry loop to VSockChannelStart() to recover on start failure. On failure, a vsock RPC channel will eventually fallback to the backdoor channel. Services that require or are limited to the priviledge RPC channel will fail. Adding a simple, limited loop in VSockChannelStart to retry the vsock channel start before ultimately switching to the backdoor channel. Retries are not done for "send once" operations. --- diff --git a/open-vm-tools/lib/rpcChannel/glib_stubs.c b/open-vm-tools/lib/rpcChannel/glib_stubs.c index 97516064d..c32deb073 100644 --- a/open-vm-tools/lib/rpcChannel/glib_stubs.c +++ b/open-vm-tools/lib/rpcChannel/glib_stubs.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2018 VMware, Inc. All rights reserved. + * Copyright (C) 2018-2020 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published @@ -41,3 +41,5 @@ void g_mutex_init(GMutex *mutex) { } void g_mutex_clear(GMutex *mutex) { } void g_mutex_lock(GMutex *mutex) { } void g_mutex_unlock(GMutex *mutex) { } + +void g_usleep(gulong microseconds) { } diff --git a/open-vm-tools/lib/rpcChannel/vsockChannel.c b/open-vm-tools/lib/rpcChannel/vsockChannel.c index 089819042..cffed9614 100644 --- a/open-vm-tools/lib/rpcChannel/vsockChannel.c +++ b/open-vm-tools/lib/rpcChannel/vsockChannel.c @@ -33,6 +33,14 @@ #define LGPFX "VSockChan: " +/* + * Time to wait in milliseconds before retrying a vsock RPC start + */ +#define VSOCK_START_RETRY_WAIT_TIME 100 + +/* Maximum number of times to retry a failed vsock RPC Channel start. */ +#define VSOCK_CHANNEL_START_MAX_RETRIES 2 + typedef struct VSockOut { SOCKET fd; char *payload; @@ -353,6 +361,24 @@ VSockChannelStart(RpcChannel *chan) // IN if (ret) { ret = VSockOutStart(vsock->out); + if (!ret && (vsock->out->flags & RPCCHANNEL_FLAGS_SEND_ONE) == 0) { + int retryCnt = 0; + + /* + * VMX may take some time to cleanup a previous vsocket, so delay + * the retry a little bit. The retry is needed for the cases when + * there is a channel start attempt in quick succession and the + * first attempt failed because VMX was still cleaning up the + * previous vsocket. + * + * Take a 100 msec pause. + */ + g_usleep(VSOCK_START_RETRY_WAIT_TIME * 1000); + while (!ret && (retryCnt++ < VSOCK_CHANNEL_START_MAX_RETRIES)) { + Debug(LGPFX "VSockChannel Start - retry %d\n", retryCnt); + ret = VSockOutStart(vsock->out); + } + } } chan->outStarted = ret;