]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
HGFS: Fix notification cleanup session tear down
authorVMware, Inc <>
Wed, 18 Sep 2013 03:10:54 +0000 (20:10 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Sat, 21 Sep 2013 22:55:50 +0000 (15:55 -0700)
Previously, when a transport session was disconnected any notifications
for the HGFS session were then removed if notification module was enabled.

However, this is grossly inadequate, as an HGFS session can come and go driven by
a client's protocol requests. The notifications are per HGFS session which is
completely independent from the transport session. The only reason the transport
session comes into play is whether it has the transport characteristics to support
the bidirectional nature of the notification feature.
When an HGFS session is destroyed whether it is from a tranport connection
session disconnect or a destroy HGFS session protocol request any folder
the outstanding notifications for the session should be removed.
Since that currently does not happen, e.g. when an HGFS session is destroyed via the
protocol requests from a client and goes on to create a new one, during
a Windows VM reboot, then when host updates do occur on an HGFS share the
notifications will be generated that hold pointers to invalid sessions.
This causes the VMX to crash.

The fix is simply to move the notification teardown for a session is at the session
teardown function, from the transport session disconnect.

Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
open-vm-tools/lib/hgfsServer/hgfsServer.c

index 3ff5b43643b51d35f96a5a6ad8462e7cf3082381..b8eb50ad327c4af4280352f13eaec79b816a3631 100644 (file)
@@ -4155,10 +4155,7 @@ HgfsDisconnectSessionInt(HgfsSessionInfo *session)    // IN: session context
    ASSERT(session->nodeArray);
    ASSERT(session->searchArray);
 
-   if (session->flags & HGFS_SESSION_CHANGENOTIFY_ENABLED) {
-      LOG(8, ("%s: calling notify component to disconnect\n", __FUNCTION__));
-      HgfsNotify_RemoveSessionSubscribers(session);
-   }
+   session->state = HGFS_SESSION_STATE_CLOSED;
    LOG(8, ("%s: exit\n", __FUNCTION__));
 }
 
@@ -4255,7 +4252,7 @@ HgfsServerSessionClose(void *clientData)    // IN: session context
  *    TRUE on success, FALSE otherwise.
  *
  * Side effects:
- *    Allocates new session info.
+ *    None.
  *
  *-----------------------------------------------------------------------------
  */
@@ -4269,6 +4266,21 @@ HgfsServerExitSessionInternal(HgfsSessionInfo *session)    // IN: session contex
    ASSERT(session->nodeArray);
    ASSERT(session->searchArray);
 
+   ASSERT(session->state == HGFS_SESSION_STATE_CLOSED);
+
+   /* Check and remove any notification handles we have for this session. */
+   if (session->flags & HGFS_SESSION_CHANGENOTIFY_ENABLED) {
+      LOG(8, ("%s: calling notify component to disconnect\n", __FUNCTION__));
+      /*
+       * This routine will synchronize itself with notification generator.
+       * Therefore, it will remove subscribers and prevent the event generator
+       * from generating any new events while it locks the subscribers lists.
+       * New events will continue once more but with the updated subscriber list
+       * that will not contain this session.
+       */
+      HgfsNotify_RemoveSessionSubscribers(session);
+   }
+
    MXUser_AcquireExclLock(session->nodeArrayLock);
 
    Log("%s: exit session %p id %"FMT64"x\n", __FUNCTION__, session, session->sessionId);
@@ -8285,6 +8297,12 @@ HgfsServerDirWatchEvent(HgfsSharedFolderHandle sharedFolder, // IN: shared folde
    LOG(4, ("%s:Entered shr hnd %u hnd %"FMT64"x file %s mask %u\n",
          __FUNCTION__, sharedFolder, subscriber, fileName, mask));
 
+   if (session->state == HGFS_SESSION_STATE_CLOSED) {
+      LOG(4, ("%s: session has been closed drop the notification %"FMT64"x\n",
+              __FUNCTION__, session->sessionId));
+      goto exit;
+   }
+
    if (!HgfsServerGetShareName(sharedFolder, &shareNameLen, &shareName)) {
       LOG(4, ("%s: failed to find shared folder for a handle %x\n",
               __FUNCTION__, sharedFolder));