]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Add a retry loop to VSockChannelStart() to recover on start failure.
authorOliver Kurth <okurth@vmware.com>
Wed, 1 Apr 2020 18:34:06 +0000 (11:34 -0700)
committerOliver Kurth <okurth@vmware.com>
Wed, 1 Apr 2020 18:34:06 +0000 (11:34 -0700)
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.

open-vm-tools/lib/rpcChannel/glib_stubs.c
open-vm-tools/lib/rpcChannel/vsockChannel.c

index 97516064d12fbfd3e644f82e4f51863c8699999a..c32deb0733efea45e7cab97afbfd0f2f2a4aa7cd 100644 (file)
@@ -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) { }
index 0898190420ba1752594bed7c3d25e7800c97d811..cffed9614c2b705539e0c4aea76a7505d3f5018d 100644 (file)
 
 #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;