]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
lib/file: file locking upgrade
authorVMware, Inc <>
Wed, 20 Jul 2011 20:47:43 +0000 (13:47 -0700)
committerMarcelo Vanzin <mvanzin@vmware.com>
Wed, 20 Jul 2011 20:47:43 +0000 (13:47 -0700)
Improve the robustness and information logging of the process
validation used by the file locking code.

Define an improved, upwards compatible format for the execution
ID such that is is possible to include the name of the process
should it be available. This change is done such that older
code will run properly, even if it sees a newer lock file.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
open-vm-tools/lib/file/fileInt.h
open-vm-tools/lib/file/fileLockPosix.c
open-vm-tools/lib/file/fileLockPrimitive.c

index 2a482878aa1e793c5afc3a46b5b15dfb0c2199a1..5abf67012dc68f574eba10b380bb28a3b2570853 100644 (file)
@@ -197,7 +197,6 @@ typedef struct lock_values
 {
    char         *machineID;
    char         *executionID;
-   char         *payload;
    char         *lockType;
    char         *locationChecksum;
    Unicode       memberName;
@@ -234,7 +233,6 @@ int FileLockMemberValues(ConstUnicode lockDir,
 FileLockToken *FileLockIntrinsic(ConstUnicode filePathName,
                                  Bool exclusivity,
                                  uint32 msecMaxWaitTime,
-                                 const char *payload,
                                  int *err);
 
 int FileUnlockIntrinsic(FileLockToken *tokenPtr);
@@ -242,8 +240,7 @@ int FileUnlockIntrinsic(FileLockToken *tokenPtr);
 Bool FileLockIsLocked(ConstUnicode filePath,
                       int *err);
 
-Bool FileLockValidOwner(const char *executionID,
-                        const char *payload);
+Bool FileLockValidExecutionID(const char *executionID);
 
 Bool FileLockValidName(ConstUnicode fileName);
 
index 8ac0a44a45952266dc599e5b6cde21b53c9b5291..4e2f413b6209613c0a18f29f0c28303392e585b8 100644 (file)
@@ -65,6 +65,9 @@
 
 #define DEVICE_LOCK_DIR "/var/lock"
 
+#define LOG_MAX_PROC_NAME  64
+
+
 /*
  * XXX
  * Most of these warnings must be turned back into Msg_Appends, or the
@@ -607,8 +610,8 @@ FileLock_UnlockDevice(const char *deviceName)  // IN:
 
 static int
 FileReadSlashProc(const char *procPath,  // IN:
-              char *buffer,          // OUT:
-              size_t bufferSize)     // IN:
+                  char *buffer,          // OUT:
+                  size_t bufferSize)     // IN:
 {
    int fd;
    int err;
@@ -647,38 +650,53 @@ FileReadSlashProc(const char *procPath,  // IN:
 
 
 /*
- *----------------------------------------------------------------------
+ *---------------------------------------------------------------------------
+ *
+ * FileLockProcessDescriptor --
+ *
+ *      Returns the process descriptor of the specified process.
  *
- * FileProcessCreationTime --
+ *      The format of a process descriptor is as follows:
  *
- *      Return the specified process's creation time.
+ *      processID-processCreationTime(processName)
+ *
+ *      where the processName and processCreationTime information
+ *      may be independently optional.
  *
  * Results:
- *      The process's creation time is returned. If an error occurs the
- *      reported creation time will be 0.
+ *      NULL The process does not exist.
+ *     !NULL The process descriptor is returned. It is the callers
+ *           responsibility to free the dynamically allocated memory.
  *
- * Side effects:
- *      None.
+ * Side Effects:
+ *     None
  *
- *----------------------------------------------------------------------
+ *---------------------------------------------------------------------------
  */
 
-static uint64
-FileProcessCreationTime(pid_t pid)  // IN:
+static char *
+FileLockProcessDescriptor(pid_t pid)  // IN:
 {
    int err;
    char path[64];
+   char *descriptor;
    char buffer[1024];
-   uint64 creationTime;
+
+   if (!FileLockIsValidProcess(pid)) {
+      return NULL;
+   }
 
    Str_Sprintf(path, sizeof path, "/proc/%d/stat", pid);
 
    err = FileReadSlashProc(path, buffer, sizeof buffer);
 
    if (err == 0) {
-      uint32 i;
-      char   *p;
-      char   *last = NULL;
+      char *p;
+      char *q;
+      char *rest;
+      uint32 argc;
+      char *argv[22];
+      char *savePtr = NULL;
 
       /*
        * You are in a maze of twisty little fields, (virtually) all alike...
@@ -687,136 +705,198 @@ FileProcessCreationTime(pid_t pid)  // IN:
        *
        * A "man 5 proc" will provide illumination concerning all of the
        * fields found on this line of text. We code for the worst case
-       * and insure that file names containing spaces or parens are
+       * and ensure that file names containing spaces or parens are
        * properly handled.
        */
 
-      p = strrchr(buffer, ')');
-      ASSERT(p != NULL);
-      p = strtok_r(++p, " ", &last);
-      ASSERT(p != NULL);
+      p = strchr(buffer, '(');
+
+      if ((p == NULL) || (p == buffer) || (*(p - 1) != ' ')) {
+         argc = 0;
+         goto bail;
+      }
+
+      *(p - 1) = '\0';
+
+      q = strrchr(p + 1, ')');
+      if (q == NULL) {
+         argc = 0;
+         goto bail;
+      }
 
-      for (i = 0; i < 19; i++) {
-         p = strtok_r(NULL, " ", &last);
-         ASSERT(p != NULL);
+      rest = q + 1;
+      if (*rest != ' ') {
+         argc = 0;
+         goto bail;
       }
 
-      if (sscanf(p, "%"FMT64"u", &creationTime) != 1) {
-         Warning(LGPFX" %s creationTime conversion error on %s.\n",
-                 __FUNCTION__, p);
+      *rest++ = '\0';
+
+      argv[0] = strtok_r(buffer, " ", &savePtr);  // ensure no trailing spaces
+      argv[1] = p;
+
+      /* Map spaces in the process name to something benign */
+      q = p;
 
-         creationTime = 0;
+      while ((q = strchr(q, ' ')) != NULL) {
+         *q = '_';
+      }
+
+      if (strlen(p) > LOG_MAX_PROC_NAME) {
+         p[LOG_MAX_PROC_NAME - 1] = ')';
+         p[LOG_MAX_PROC_NAME] = '\0';
+      }
+
+      for (argc = 2; argc < 22; argc++) {
+         argv[argc] = strtok_r((argc == 2) ? rest : NULL, " ", &savePtr);
+
+         if (argv[argc] == NULL) {
+            break;
+         }
+      }
+
+bail:
+
+      if (argc == 22) {
+         descriptor = Str_SafeAsprintf(NULL, "%s-%s%s", argv[0], argv[21],
+                                       argv[1]);
+      } else {
+         /*
+          * Since /proc didn't parse properly, emit a valid string that
+          * also provides a clue that there is problem.
+          */
+
+         descriptor = Str_SafeAsprintf(NULL, "%d-0", pid);
       }
    } else {
-      creationTime = 0;
+      descriptor = NULL;
    }
 
-   return creationTime;
+   return descriptor;
 }
 #elif defined(__APPLE__)
-static uint64
-FileProcessCreationTime(pid_t pid)  // IN:
-{
-    int err;
-    size_t size;
-    struct kinfo_proc  info;
-    int mib[4];
-  
-    /* Request information about the specified process */
-    mib[0] = CTL_KERN;
-    mib[1] = KERN_PROC;
-    mib[2] = KERN_PROC_PID;
-    mib[3] = pid;
-
-    memset(&info, 0, sizeof info);
-    size = sizeof(info);
-    err = sysctl(mib, ARRAYSIZE(mib), &info, &size, NULL, 0);
-
-    /* Log any failures */
-    if (err == -1) {
-       Warning(LGPFX" %s sysctl for pid %d failed: %s\n", __FUNCTION__,
-               pid, Err_Errno2String(errno));
-
-       return 0;
-    }
-
-    /* Return the process creation time */
-    return (info.kp_proc.p_starttime.tv_sec * CONST64U(1000000)) +
-            info.kp_proc.p_starttime.tv_usec;
-}
-#else
-static uint64
-FileProcessCreationTime(pid_t pid)  // IN:
-{
-   return 0;
-}
-#endif
-
-
 /*
- *----------------------------------------------------------------------
+ *---------------------------------------------------------------------------
  *
- * FileLockValidOwner --
+ * FileLockProcessCreationTime --
  *
- *      Validate the lock file owner.
+ *      Returns the process creation time of the specified process.
  *
  * Results:
- *      TRUE    Yes
- *      FALSE   No
+ *      TRUE  Done!
+ *      FALSE Process doesn't exist
  *
  * Side effects:
- *      None.
+ *      None
  *
- *----------------------------------------------------------------------
+ *---------------------------------------------------------------------------
  */
 
-Bool
-FileLockValidOwner(const char *executionID,  // IN:
-                   const char *payload)      // IN:
+static Bool
+FileLockProcessCreationTime(pid_t pid,                 // IN:
+                            uint64 *procCreationTime)  // OUT:
 {
-   int pid;
+   int err;
+   size_t size;
+   struct kinfo_proc info;
+   int mib[4];
 
-   /* Validate the PID. */
-   if (sscanf(executionID, "%d", &pid) != 1) {
-      Warning(LGPFX" %s pid conversion error on %s. Assuming valid.\n",
-              __FUNCTION__, executionID);
+   ASSERT(procCreationTime);
 
-      return TRUE;
-   }
+   /* Request information about the specified process */
+   mib[0] = CTL_KERN;
+   mib[1] = KERN_PROC;
+   mib[2] = KERN_PROC_PID;
+   mib[3] = pid;
 
-   if (!FileLockIsValidProcess(pid)) {
+   memset(&info, 0, sizeof info);
+   size = sizeof info;
+   err = sysctl(mib, ARRAYSIZE(mib), &info, &size, NULL, 0);
+
+   if (err == -1) {
       return FALSE;
    }
 
-   /* If there is a payload perform additional validation. */
-   if (payload != NULL) {
-      uint64 fileCreationTime;
-      uint64 processCreationTime;
+   *procCreationTime = (info.kp_proc.p_starttime.tv_sec * CONST64U(1000000)) +
+                        info.kp_proc.p_starttime.tv_usec;
 
-      /*
-       * The payload is the process creation time of the process that
-       * created the lock file.
-       */
+   return TRUE;
+}
 
-      if (sscanf(payload, "%"FMT64"u", &fileCreationTime) != 1) {
-         Warning(LGPFX" %s payload conversion error on %s. Assuming valid.\n",
-                 __FUNCTION__, payload);
 
-         return TRUE;
-      }
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FileLockProcessDescriptor --
+ *
+ *      Returns the process descriptor of the specified process.
+ *
+ *      The format of a process descriptor is as follows:
+ *
+ *      processID-processCreationTime(processName)
+ *
+ *      where the processName and processCreationTime information
+ *      may be independently optional.
+ *
+ * Results:
+ *      NULL The process does not exist.
+ *     !NULL The process descriptor is returned. It is the callers
+ *           responsibility to free the dynamically allocated memory.
+ *
+ * Side effects:
+ *      None
+ *
+ *---------------------------------------------------------------------------
+ */
 
-      /* Non-matching process creation times -> pid is not the creator */
-      processCreationTime = FileProcessCreationTime(pid);
+static char *
+FileLockProcessDescriptor(pid_t pid)  // IN:
+{
+   uint64 procCreationTime;
 
-      if ((fileCreationTime != 0) &&
-          (processCreationTime != 0) &&
-          (fileCreationTime != processCreationTime)) {
-         return FALSE;
-      }
+   if (!FileLockIsValidProcess(pid)) {
+      return NULL;
    }
 
-   return TRUE;
+   if (!FileLockProcessCreationTime(pid, &procCreationTime)) {
+      return NULL;
+   }
+
+   return Str_SafeAsprintf(NULL, "%d-%"FMT64"u", pid, procCreationTime);
 }
+#else
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FileLockProcessDescriptor --
+ *
+ *      Returns the process descriptor of the specified process.
+ *
+ *      The format of a process descriptor is as follows:
+ *
+ *      processID-processCreationTime(processName)
+ *
+ *      where the processName and processCreationTime information
+ *      may be independently optional.
+ *
+ * Results:
+ *      NULL The process does not exist.
+ *     !NULL The process descriptor is returned. It is the callers
+ *           responsibility to free the dynamically allocated memory.
+ *
+ * Side effects:
+ *      None
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static char *
+FileLockProcessDescriptor(pid_t pid)  // IN:
+{
+   return FileLockIsValidProcess(pid) ? Str_SafeAsprintf(NULL, "%d-0", pid) :
+                                        NULL;
+}
+#endif
 
 
 /*
@@ -827,7 +907,8 @@ FileLockValidOwner(const char *executionID,  // IN:
  *      Returns the executionID of the caller.
  *
  * Results:
- *      The executionID of the caller.
+ *      The executionID of the caller. This is a dynamically allocated string;
+ *      the caller is responsible for its disposal.
  *
  * Side effects:
  *      The executionID of the caller is not thread safe. Locking is currently
@@ -840,7 +921,112 @@ FileLockValidOwner(const char *executionID,  // IN:
 char *
 FileLockGetExecutionID(void)
 {
-   return Str_SafeAsprintf(NULL, "%d", getpid());
+   char *descriptor = FileLockProcessDescriptor(getpid());
+
+   ASSERT(descriptor);  // Must be able to describe ourselves!
+
+   return descriptor;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FileLockParseProcessDescriptor --
+ *
+ *      Attempt to parse the specified process descriptor. Return the
+ *      pieces requested.
+ *
+ * Results:
+ *      TRUE  Process descriptor is valid.
+ *      FALSE Process descriptor is invalid.
+ *
+ * Side effects:
+ *      None
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static Bool
+FileLockParseProcessDescriptor(const char *procDescriptor,  // IN:
+                               pid_t *pid,                  // OUT:
+                               uint64 *procCreationTime)    // OUT:
+{
+   ASSERT(procDescriptor);
+   ASSERT(pid);
+   ASSERT(procCreationTime);
+
+   if (sscanf(procDescriptor, "%d-%"FMT64"u", pid, procCreationTime) != 2) {
+      if (sscanf(procDescriptor, "%d", pid) == 1) {
+         *procCreationTime = 0ULL;
+      } else {
+         return FALSE;
+      }
+   }
+   return *pid >= 0;  
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FileLockValidExecutionID --
+ *
+ *      Validate the execution ID.
+ *
+ * Results:
+ *      TRUE    Yes
+ *      FALSE   No
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Bool
+FileLockValidExecutionID(const char *executionID)  // IN:
+{
+   pid_t filePID;
+   pid_t procPID;
+   Bool gotFileData;
+   Bool gotProcData;
+   char *procDescriptor;
+   uint64 fileCreationTime;
+   uint64 procCreationTime;
+
+   gotFileData = FileLockParseProcessDescriptor(executionID, &filePID,
+                                                &fileCreationTime);
+
+   if (!gotFileData) {
+      Warning(LGPFX" %s parse error on '%s'. Assuming valid.\n",
+              __FUNCTION__, executionID);
+
+      return TRUE;  // Assume TRUE - preserve a lock - on parse error
+   }
+
+   procDescriptor = FileLockProcessDescriptor(filePID);
+
+   if (procDescriptor == NULL) {
+      return FALSE;  // process doesn't exist
+   }
+
+   gotProcData = FileLockParseProcessDescriptor(procDescriptor, &procPID,
+                                                &procCreationTime);
+
+   ASSERT(gotProcData);         // We built it; it had better be good
+   ASSERT(procPID == filePID);  // This better match what we started with...
+
+   free(procDescriptor);
+
+   if ((fileCreationTime != 0) &&
+       (procCreationTime != 0) &&
+       (fileCreationTime != procCreationTime)) {
+      return FALSE;  // The process no longer exists
+   } else {
+      return TRUE;  // Looks valid...
+   }
 }
 
 
@@ -938,13 +1124,8 @@ FileLock_Lock(ConstUnicode filePath,         // IN:
 
       tokenPtr = NULL;
    } else {
-      char creationTimeString[32];
-
-      Str_Sprintf(creationTimeString, sizeof creationTimeString, "%"FMT64"u",
-                  FileProcessCreationTime(getpid()));
-
       tokenPtr = FileLockIntrinsic(normalizedPath, !readOnly, msecMaxWaitTime,
-                                   creationTimeString, err);
+                                   err);
 
       Unicode_Free(normalizedPath);
    }
index e4145fa6d5e72c990369c212ce37f90b4b40f7e0..ac21625148c767b92f5a8f151e2d32763e15f814 100644 (file)
@@ -299,10 +299,12 @@ FileLockMemberValues(ConstUnicode lockDir,      // IN:
    uint32 argc = 0;
    char *saveptr = NULL;
 
-   ParseTable table = { PARSE_TABLE_STRING,
-                        "lc",
-                        (void *) &memberValues->locationChecksum
-                      };
+   ParseTable table[] = {
+                           { PARSE_TABLE_STRING,
+                             "lc",
+                             (void *) &memberValues->locationChecksum
+                           }
+                        };
  
    ASSERT(lockDir);
    ASSERT(fileName);
@@ -391,6 +393,8 @@ FileLockMemberValues(ConstUnicode lockDir,      // IN:
       goto bail;
    }
 
+fixedUp:
+
    /* Extract and validate the lock file data. */
    for (argc = 0; argc < FL_MAX_ARGS; argc++) {
       argv[argc] = strtok_r((argc == 0) ? buffer : NULL, " ", &saveptr);
@@ -400,49 +404,61 @@ FileLockMemberValues(ConstUnicode lockDir,      // IN:
       }
    }
 
-   if ((argc < 4) || ((argc == FL_MAX_ARGS) &&
-                       (strtok_r(NULL, " ", &saveptr) != NULL))) {
-      goto corrupt;
-   }
-
    /*
-    * Lock file arguments are space separated. There is a minimum of 4
-    * arguments - machineID, executionID, Lamport number and lock type.
-    * The maximum number of arguments is FL_MAX_ARGS.
+    * Lock file arguments are space separated. There is a minimum of 5
+    * arguments - machineID, executionID, Lamport number, lock type
+    * and process creation time. The maximum number of arguments is
+    * FL_MAX_ARGS.
     *
-    * The fifth argument, if present, is the payload or "[" if there is no
-    * payload and additional arguments are present. The additional arguments
-    * form  a properly list - one or more "name=value" pairs.
+    * Additional arguments, if present, form a property list - one or more
+    * "name=value" pairs.
     *
     * Here is picture of valid forms:
     *
     * 0 1 2 3 4 5 6   Comment
     *-------------------------
-    * A B C D         contents, no payload, no list entries
-    * A B C D [       contents, no payload, no list entries
-    * A B C D P       contents, a payload,  no list entries
-    * A B C D [ x     contents, no payload, one list entry
-    * A B C D P x     contents, a payload,  one list entry
-    * A B C D [ x y   contents, no payload, two list entries
-    * A B C D P x y   contents, a payload,  two list entries
+    * A B C D E       No property list
+    * A B C D E x     One property
+    * A B C D E x y   Two properties
     */
 
    memberValues->locationChecksum = NULL;
 
-   if (argc == 4) {
-      memberValues->payload = NULL;
-   } else {
-      if (strcmp(argv[4], "[") == 0) {
-         memberValues->payload = NULL;
-      } else {
-         memberValues->payload = argv[4];
-      }
+   if ((argc < 5) || ((argc == FL_MAX_ARGS) &&
+                       (strtok_r(NULL, " ", &saveptr) != NULL))) {
+      goto corrupt;
+   }
 
-      if (FileLockParseArgs(argv, argc - 5, &table, 1)) {
-         goto corrupt;
-      }
+   if ((argc > 5) && FileLockParseArgs(argv, argc - 5,
+                                       table, ARRAYSIZE(table))) {
+      goto corrupt;
    }
 
+   /*
+    * Check for an old style lock file; if found, upgrade it (internally).
+    *
+    * The new style lock always has an executionID that is minimally
+    * processID-processCreationTime (the '-' is the critical difference).
+    */
+
+   if ((strchr(argv[1], '-') == NULL) &&
+       (strchr(argv[1], '(') == NULL) &&
+       (strchr(argv[1], ')') == NULL) &&
+       (argc == 6) &&
+       !FileLockParseArgs(argv, argc - 5, table, ARRAYSIZE(table))) {
+         char *newBuffer;
+
+         newBuffer = Str_SafeAsprintf(NULL, "%s %s-%s %s %s %s %s",
+                                      argv[0], argv[1], argv[4], argv[2],
+                                      argv[3], argv[4], argv[5]);
+
+        Str_Strcpy(buffer, newBuffer, requiredSize);
+
+        free(newBuffer);
+
+        goto fixedUp;
+  }
+
    if (sscanf(argv[2], "%u", &memberValues->lamportNumber) != 1) {
       goto corrupt;
    }
@@ -762,8 +778,7 @@ FileLockScanDirectory(ConstUnicode lockDir,     // IN:
                                     memberValues.machineID)) {
             char *dispose = NULL;
 
-            if (FileLockValidOwner(memberValues.executionID,
-                                   memberValues.payload)) {
+            if (FileLockValidExecutionID(memberValues.executionID)) {
                /* If it's mine it better still be where I put it! */
                if ((strcmp(myExecutionID, memberValues.executionID) == 0) &&
                    ((memberValues.locationChecksum != NULL) &&
@@ -1078,8 +1093,8 @@ FileLockWaitForPossession(ConstUnicode lockDir,      // IN:
          }
 
          /* still valid? */
-         if (thisMachine && !FileLockValidOwner(memberValues->executionID,
-                                                memberValues->payload)) {
+         if (thisMachine &&
+             !FileLockValidExecutionID(memberValues->executionID)) {
             /* Invalid Execution ID; remove the member file */
             Warning(LGPFX" %s discarding file '%s'; invalid executionID.\n",
                     __FUNCTION__, UTF8(path));
@@ -1097,10 +1112,10 @@ FileLockWaitForPossession(ConstUnicode lockDir,      // IN:
       if ((myValues->msecMaxWaitTime != FILELOCK_TRYLOCK_WAIT) &&
           (err == EAGAIN)) {
          if (thisMachine) {
-            Log(LGPFX" %s timeout on '%s' due to a local process (%s)\n",
+            Log(LGPFX" %s timeout on '%s' due to a local process '%s'\n",
                     __FUNCTION__, UTF8(path), memberValues->executionID);
          } else {
-            Log(LGPFX" %s timeout on '%s' due to another machine (%s)\n",
+            Log(LGPFX" %s timeout on '%s' due to another machine '%s'\n",
                     __FUNCTION__, UTF8(path), memberValues->machineID);
          }
       }
@@ -1386,8 +1401,11 @@ FileLockCreateMemberFile(FileIODescriptor *desc,       // IN:
                          ConstUnicode entryFilePath,   // IN:
                          ConstUnicode memberFilePath)  // IN:
 {
+   int cnt;
+   int pid;
    size_t len;
    FileIOResult result;
+   uint64 processCreationTime;
 
    int err = 0;
    char buffer[FILELOCK_DATA_SIZE] = { 0 };
@@ -1398,21 +1416,32 @@ FileLockCreateMemberFile(FileIODescriptor *desc,       // IN:
    /*
     * Populate the buffer with appropriate data
     *
-    * Lock file arguments are space separated. There is a minimum of 4
-    * arguments - machineID, executionID, Lamport number and lock type.
-    * The maximum number of argument is FL_MAX_ARGS.
+    * Lock file arguments are space separated. There is a minimum of 5
+    * arguments - machineID, executionID, Lamport number, lock type
+    * and process creation time. The maximum number of arguments is
+    * FL_MAX_ARGS.
     *
-    * The fifth argument, if present, is the payload or "[" if there is no
-    * payload and additional arguments are present. The additional arguments
-    * form  a properly list - one or more "name=value" pairs.
+    * Additional arguments, if present, form a property list - one or more
+    * "name=value" pairs.
+    *
+    * Yes, the process creation time is redundently encoded. This is necessary
+    * to maintain backwards compatibility. Should an older code pick up a
+    * newer lock file and there is lock contention, the older code will log
+    * the name of the process causing the contention - it's also encoded
+    * into the executionID.
     */
 
-   Str_Sprintf(buffer, sizeof buffer, "%s %s %u %s %s lc=%s",
+   cnt = sscanf(myValues->executionID, "%d-%"FMT64"u", &pid,
+                &processCreationTime);
+
+   ASSERT(cnt == 2);  // ensure new format executionID
+
+   Str_Sprintf(buffer, sizeof buffer, "%s %s %u %s %"FMT64"u lc=%s",
                myValues->machineID,
                myValues->executionID,
                myValues->lamportNumber,
                myValues->lockType,
-               myValues->payload == NULL ? "[" : myValues->payload,
+               processCreationTime,
                myValues->locationChecksum);
 
    /* Attempt to write the data */
@@ -1499,7 +1528,6 @@ FileLockToken *
 FileLockIntrinsic(ConstUnicode pathName,   // IN:
                   Bool exclusivity,        // IN:
                   uint32 msecMaxWaitTime,  // IN:
-                  const char *payload,     // IN:
                   int *err)                // OUT:
 {
    int access;
@@ -1523,7 +1551,6 @@ FileLockIntrinsic(ConstUnicode pathName,   // IN:
 
    myValues.machineID = (char *) FileLockGetMachineID(); // don't free this!
    myValues.executionID = FileLockGetExecutionID();      // free this!
-   myValues.payload = (char *) payload;
    myValues.lockType = exclusivity ? LOCK_EXCLUSIVE : LOCK_SHARED;
    myValues.lamportNumber = 0;
    myValues.locationChecksum = FileLockLocationChecksum(lockDir); // free this!