Index: /trunk/src/VBox/ValidationKit/testdriver/base.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testdriver/base.py	(revision 65198)
+++ /trunk/src/VBox/ValidationKit/testdriver/base.py	(revision 65199)
@@ -1139,7 +1139,7 @@
         """
         Worker that reads the PID file.
-        Returns list of PID, empty if no file.
-        """
-        aiPids = [];
+        Returns dictionary of PID with value (sName, fSudo), empty if no file.
+        """
+        dPids = {};
         if os.path.isfile(self.sPidFile):
             try:
@@ -1149,19 +1149,20 @@
             except:
                 reporter.errorXcpt();
-                return aiPids;
+                return dPids;
 
             sContent = str(sContent).strip().replace('\n', ' ').replace('\r', ' ').replace('\t', ' ');
-            for sPid in sContent.split(' '):
-                if sPid.isdigit():
+            for sProcess in sContent.split(' '):
+                asFields = sProcess.split(':');
+                if len(asFields) == 3 and asFields[0].isdigit():
                     try:
-                        aiPids.append(int(sPid));
+                        dPids[int(asFields[0])] = (asFields[2], asFields[1] == 'sudo');
                     except:
-                        reporter.logXcpt('sPid=%s' % (sPid,));
+                        reporter.logXcpt('sProcess=%s' % (sProcess,));
                 else:
-                    reporter.log('%s: "%s"' % (self.sPidFile, sPid));
-
-        return aiPids;
-
-    def pidFileAdd(self, iPid, fSudo = False):
+                    reporter.log('%s: "%s"' % (self.sPidFile, sProcess));
+
+        return dPids;
+
+    def pidFileAdd(self, iPid, sName, fSudo = False):
         """
         Adds a PID to the PID file, creating the file if necessary.
@@ -1170,5 +1171,8 @@
         try:
             oFile = utils.openNoInherit(self.sPidFile, 'a');
-            oFile.write(str(iPid) + '\n');
+            oFile.write('%s:%s:%s\n'
+                        % ( iPid,
+                            'sudo' if fSudo else 'normal',
+                             sName.replace(' ', '_').replace(':','_').replace('\n','_').replace('\r','_').replace('\t','_'),));
             oFile.close();
         except:
@@ -1182,14 +1186,16 @@
         Removes a PID from the PID file.
         """
-        aiPids = self.pidFileRead();
-        if iPid not in aiPids:
+        dPids = self.pidFileRead();
+        if iPid not in dPids:
             if not fQuiet:
-                reporter.log('pidFileRemove could not find %s in the PID file (content: %s)' % (iPid, aiPids));
+                reporter.log('pidFileRemove could not find %s in the PID file (content: %s)' % (iPid, dPids));
             return False;
 
-        aiPids.remove(iPid);
+        sName = dPids[iPid][0];
+        del dPids[iPid];
+
         sPid = '';
-        for iPid2 in aiPids:
-            sPid += '%s\n' % (iPid2,);
+        for iPid2 in dPids:
+            sPid += '%s:%s:%s\n' % (iPid2, 'sudo' if dPids[iPid2][1] else 'normal', dPids[iPid2][0]);
 
         try:
@@ -1201,5 +1207,5 @@
             return False;
 
-        reporter.log2('pidFileRemove: removed PID %d (new content: %s)' % (iPid, self.pidFileRead(),));
+        reporter.log2('pidFileRemove: removed PID %d [%s] (new content: %s)' % (iPid, sName, self.pidFileRead(),));
         return True;
 
@@ -1516,6 +1522,6 @@
         """
 
-        aiPids = self.pidFileRead();
-        reporter.log('The pid file contained: %s' % (aiPids,));
+        dPids = self.pidFileRead();
+        reporter.log('The pid file contained: %s' % (dPids,));
 
         #
@@ -1527,5 +1533,6 @@
             afnMethods = [ sendUserSignal1, processInterrupt, processTerminate, processKill ];
         for fnMethod in afnMethods:
-            for iPid in aiPids:
+            ## @todo Handle SUDO processes.
+            for iPid in dPids:
                 fnMethod(iPid);
 
@@ -1534,19 +1541,18 @@
                     time.sleep(1);
 
-                for j in range(len(aiPids) - 1, -1, -1):
-                    iPid = aiPids[j];
+                for iPid in dPids.keys():
                     if not processExists(iPid):
-                        reporter.log('%s terminated' % (iPid,));
+                        reporter.log('%s (%s) terminated' % (dPids[iPid][0], iPid,));
                         self.pidFileRemove(iPid, fQuiet = True);
-                        aiPids.pop(j);
-
-                if len(aiPids) == 0:
+                        del dPids[iPid];
+
+                if len(dPids) == 0:
                     reporter.log('All done.');
                     return True;
 
                 if i in [4, 8]:
-                    reporter.log('Still waiting for: %s (method=%s)' % (aiPids, fnMethod,));
-
-        reporter.log('Failed to terminate the following processes: %s' % (aiPids,));
+                    reporter.log('Still waiting for: %s (method=%s)' % (dPids, fnMethod,));
+
+        reporter.log('Failed to terminate the following processes: %s' % (dPids,));
         return False;
 
@@ -1661,5 +1667,5 @@
                 reporter.log('*** cleanup-before action completed (fRc2=%s, fRc=%s) ***' % (fRc2, fRc,));
 
-            self.pidFileAdd(os.getpid());
+            self.pidFileAdd(os.getpid(), os.path.basename(sys.argv[0]));
 
             if 'config' in asActions and fRc is True:
@@ -1730,9 +1736,20 @@
 
     def testPidFile(self):
-        aiPids = [os.getpid() + 1, os.getpid() + 2];
-        self.assertTrue(self.oTstDrv.pidFileAdd(aiPids[0]));
-        self.assertEqual(self.oTstDrv.pidFileRead(), aiPids[0:1]);
-        self.assertTrue(self.oTstDrv.pidFileAdd(aiPids[1]));
-        self.assertEqual(self.oTstDrv.pidFileRead(), aiPids[0:2]);
+
+        iPid1 = os.getpid() + 1;
+        iPid2 = os.getpid() + 2;
+
+        self.assertTrue(self.oTstDrv.pidFileAdd(iPid1, 'test1'));
+        self.assertEqual(self.oTstDrv.pidFileRead(), {iPid1:('test1',False)});
+
+        self.assertTrue(self.oTstDrv.pidFileAdd(iPid2, 'test2', fSudo = True));
+        self.assertEqual(self.oTstDrv.pidFileRead(), {iPid1:('test1',False), iPid2:('test2',True)});
+
+        self.assertTrue(self.oTstDrv.pidFileRemove(iPid1));
+        self.assertEqual(self.oTstDrv.pidFileRead(), {iPid2:('test2',True)});
+
+        self.assertTrue(self.oTstDrv.pidFileRemove(iPid2));
+        self.assertEqual(self.oTstDrv.pidFileRead(), {});
+
         self.assertTrue(self.oTstDrv.pidFileDelete());
 
Index: /trunk/src/VBox/ValidationKit/testdriver/vboxwrappers.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testdriver/vboxwrappers.py	(revision 65198)
+++ /trunk/src/VBox/ValidationKit/testdriver/vboxwrappers.py	(revision 65199)
@@ -2618,5 +2618,5 @@
             if self.uPid is not None:
                 reporter.log2('getPid: %u' % (self.uPid,));
-                self.oTstDrv.pidFileAdd(self.uPid);
+                self.oTstDrv.pidFileAdd(self.uPid, 'vm_%s' % (self.sName,), fSudo = True); # Set-uid-to-root is similar to SUDO.
         return self.uPid;
 
Index: /trunk/src/VBox/ValidationKit/tests/unittests/tdUnitTest1.py
===================================================================
--- /trunk/src/VBox/ValidationKit/tests/unittests/tdUnitTest1.py	(revision 65198)
+++ /trunk/src/VBox/ValidationKit/tests/unittests/tdUnitTest1.py	(revision 65199)
@@ -645,5 +645,5 @@
 
             if oChild is not None:
-                self.pidFileAdd(oChild.pid, fSudo = fHardened);
+                self.pidFileAdd(oChild.pid, sName, fSudo = fHardened);
                 iRc = oChild.wait();
                 self.pidFileRemove(oChild.pid);
