src/os/windows/vm/perfMemory_windows.cpp

Print this page


   1 /*
   2  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *


 281     }
 282   }
 283 
 284   char* user_name = NEW_C_HEAP_ARRAY(char, strlen(user)+1);
 285   strcpy(user_name, user);
 286 
 287   return user_name;
 288 }
 289 
 290 // return the name of the user that owns the process identified by vmid.
 291 //
 292 // This method uses a slow directory search algorithm to find the backing
 293 // store file for the specified vmid and returns the user name, as determined
 294 // by the user name suffix of the hsperfdata_<username> directory name.
 295 //
 296 // the caller is expected to free the allocated memory.
 297 //
 298 static char* get_user_name_slow(int vmid) {
 299 
 300   // directory search
 301   char* oldest_user = NULL;
 302   time_t oldest_ctime = 0;
 303 
 304   const char* tmpdirname = os::get_temp_directory();
 305 
 306   DIR* tmpdirp = os::opendir(tmpdirname);
 307 
 308   if (tmpdirp == NULL) {
 309     return NULL;
 310   }
 311 
 312   // for each entry in the directory that matches the pattern hsperfdata_*,
 313   // open the directory and check if the file for the given vmid exists.
 314   // The file with the expected name and the latest creation date is used
 315   // to determine the user name for the process id.
 316   //
 317   struct dirent* dentry;
 318   char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname));
 319   errno = 0;
 320   while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
 321 
 322     // check if the directory entry is a hsperfdata file


 358         struct stat statbuf;
 359 
 360         char* filename = NEW_C_HEAP_ARRAY(char,
 361                             strlen(usrdir_name) + strlen(udentry->d_name) + 2);
 362 
 363         strcpy(filename, usrdir_name);
 364         strcat(filename, "\\");
 365         strcat(filename, udentry->d_name);
 366 
 367         if (::stat(filename, &statbuf) == OS_ERR) {
 368            FREE_C_HEAP_ARRAY(char, filename);
 369            continue;
 370         }
 371 
 372         // skip over files that are not regular files.
 373         if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
 374           FREE_C_HEAP_ARRAY(char, filename);
 375           continue;
 376         }
 377 
 378         // compare and save filename with latest creation time
 379         if (statbuf.st_size > 0 && statbuf.st_ctime > oldest_ctime) {
 380 
 381           if (statbuf.st_ctime > oldest_ctime) {












 382             char* user = strchr(dentry->d_name, '_') + 1;
 383 
 384             if (oldest_user != NULL) FREE_C_HEAP_ARRAY(char, oldest_user);
 385             oldest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1);
 386 
 387             strcpy(oldest_user, user);
 388             oldest_ctime = statbuf.st_ctime;
 389           }
 390         }
 391 
 392         FREE_C_HEAP_ARRAY(char, filename);
 393       }
 394     }
 395     os::closedir(subdirp);
 396     FREE_C_HEAP_ARRAY(char, udbuf);
 397     FREE_C_HEAP_ARRAY(char, usrdir_name);
 398   }
 399   os::closedir(tmpdirp);
 400   FREE_C_HEAP_ARRAY(char, tdbuf);
 401 
 402   return(oldest_user);
 403 }
 404 
 405 // return the name of the user that owns the process identified by vmid.
 406 //
 407 // note: this method should only be used via the Perf native methods.
 408 // There are various costs to this method and limiting its use to the
 409 // Perf native methods limits the impact to monitoring applications only.
 410 //
 411 static char* get_user_name(int vmid) {
 412 
 413   // A fast implementation is not provided at this time. It's possible
 414   // to provide a fast process id to user name mapping function using
 415   // the win32 apis, but the default ACL for the process object only
 416   // allows processes with the same owner SID to acquire the process
 417   // handle (via OpenProcess(PROCESS_QUERY_INFORMATION)). It's possible
 418   // to have the JVM change the ACL for the process object to allow arbitrary
 419   // users to access the process handle and the process security token.
 420   // The security ramifications need to be studied before providing this
 421   // mechanism.
 422   //


1322     if (PrintMiscellaneous && Verbose) {
1323       warning("could not create file %s: %d\n", filename, lasterror);
1324     }
1325     return NULL;
1326   }
1327 
1328   // try to create the file mapping
1329   fmh = create_file_mapping(objectname, fh, lpSmoSA, size);
1330 
1331   free_security_attr(lpSmoSA);
1332 
1333   if (fmh == NULL) {
1334     // closing the file handle here will decrement the reference count
1335     // on the file. When all processes accessing the file close their
1336     // handle to it, the reference count will decrement to 0 and the
1337     // OS will delete the file. These semantics are requested by the
1338     // FILE_FLAG_DELETE_ON_CLOSE flag in CreateFile call above.
1339     CloseHandle(fh);
1340     fh = NULL;
1341     return NULL;









1342   }






1343 
















1344   // the file has been successfully created and the file mapping
1345   // object has been created.
1346   sharedmem_fileHandle = fh;
1347   sharedmem_fileName = strdup(filename);
1348 
1349   return fmh;
1350 }
1351 
1352 // open the shared memory object for the given vmid.
1353 //
1354 static HANDLE open_sharedmem_object(const char* objectname, DWORD ofm_access, TRAPS) {
1355 
1356   HANDLE fmh;
1357 
1358   // open the file mapping with the requested mode
1359   fmh = OpenFileMapping(
1360                ofm_access,       /* DWORD access mode */
1361                FALSE,            /* BOOL inherit flag - Do not allow inherit */
1362                objectname);      /* name for object */
1363 


   1 /*
   2  * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *


 281     }
 282   }
 283 
 284   char* user_name = NEW_C_HEAP_ARRAY(char, strlen(user)+1);
 285   strcpy(user_name, user);
 286 
 287   return user_name;
 288 }
 289 
 290 // return the name of the user that owns the process identified by vmid.
 291 //
 292 // This method uses a slow directory search algorithm to find the backing
 293 // store file for the specified vmid and returns the user name, as determined
 294 // by the user name suffix of the hsperfdata_<username> directory name.
 295 //
 296 // the caller is expected to free the allocated memory.
 297 //
 298 static char* get_user_name_slow(int vmid) {
 299 
 300   // directory search
 301   char* latest_user = NULL;
 302   time_t latest_ctime = 0;
 303 
 304   const char* tmpdirname = os::get_temp_directory();
 305 
 306   DIR* tmpdirp = os::opendir(tmpdirname);
 307 
 308   if (tmpdirp == NULL) {
 309     return NULL;
 310   }
 311 
 312   // for each entry in the directory that matches the pattern hsperfdata_*,
 313   // open the directory and check if the file for the given vmid exists.
 314   // The file with the expected name and the latest creation date is used
 315   // to determine the user name for the process id.
 316   //
 317   struct dirent* dentry;
 318   char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname));
 319   errno = 0;
 320   while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
 321 
 322     // check if the directory entry is a hsperfdata file


 358         struct stat statbuf;
 359 
 360         char* filename = NEW_C_HEAP_ARRAY(char,
 361                             strlen(usrdir_name) + strlen(udentry->d_name) + 2);
 362 
 363         strcpy(filename, usrdir_name);
 364         strcat(filename, "\\");
 365         strcat(filename, udentry->d_name);
 366 
 367         if (::stat(filename, &statbuf) == OS_ERR) {
 368            FREE_C_HEAP_ARRAY(char, filename);
 369            continue;
 370         }
 371 
 372         // skip over files that are not regular files.
 373         if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
 374           FREE_C_HEAP_ARRAY(char, filename);
 375           continue;
 376         }
 377 
 378         // If we found a matching file with a newer creation time, then
 379         // save the user name. The newer creation time indicates that
 380         // we found a newer incarnation of the process associated with
 381         // vmid. Due to the way that Windows recycles pids and the fact
 382         // that we can't delete the file from the file system namespace
 383         // until last close, it is possible for there to be more than
 384         // one hsperfdata file with a name matching vmid (diff users).
 385         //
 386         // We no longer ignore hsperfdata files where (st_size == 0).
 387         // In this function, all we're trying to do is determine the
 388         // name of the user that owns the process associated with vmid
 389         // so the size doesn't matter. Very rarely, we have observed
 390         // hsperfdata files where (st_size == 0) and the st_size field
 391         // later becomes the expected value.
 392         // 
 393         if (statbuf.st_ctime > latest_ctime) {
 394           char* user = strchr(dentry->d_name, '_') + 1;
 395 
 396           if (latest_user != NULL) FREE_C_HEAP_ARRAY(char, latest_user);
 397           latest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1);
 398 
 399           strcpy(latest_user, user);
 400           latest_ctime = statbuf.st_ctime;
 401         }

 402 
 403         FREE_C_HEAP_ARRAY(char, filename);
 404       }
 405     }
 406     os::closedir(subdirp);
 407     FREE_C_HEAP_ARRAY(char, udbuf);
 408     FREE_C_HEAP_ARRAY(char, usrdir_name);
 409   }
 410   os::closedir(tmpdirp);
 411   FREE_C_HEAP_ARRAY(char, tdbuf);
 412 
 413   return(latest_user);
 414 }
 415 
 416 // return the name of the user that owns the process identified by vmid.
 417 //
 418 // note: this method should only be used via the Perf native methods.
 419 // There are various costs to this method and limiting its use to the
 420 // Perf native methods limits the impact to monitoring applications only.
 421 //
 422 static char* get_user_name(int vmid) {
 423 
 424   // A fast implementation is not provided at this time. It's possible
 425   // to provide a fast process id to user name mapping function using
 426   // the win32 apis, but the default ACL for the process object only
 427   // allows processes with the same owner SID to acquire the process
 428   // handle (via OpenProcess(PROCESS_QUERY_INFORMATION)). It's possible
 429   // to have the JVM change the ACL for the process object to allow arbitrary
 430   // users to access the process handle and the process security token.
 431   // The security ramifications need to be studied before providing this
 432   // mechanism.
 433   //


1333     if (PrintMiscellaneous && Verbose) {
1334       warning("could not create file %s: %d\n", filename, lasterror);
1335     }
1336     return NULL;
1337   }
1338 
1339   // try to create the file mapping
1340   fmh = create_file_mapping(objectname, fh, lpSmoSA, size);
1341 
1342   free_security_attr(lpSmoSA);
1343 
1344   if (fmh == NULL) {
1345     // closing the file handle here will decrement the reference count
1346     // on the file. When all processes accessing the file close their
1347     // handle to it, the reference count will decrement to 0 and the
1348     // OS will delete the file. These semantics are requested by the
1349     // FILE_FLAG_DELETE_ON_CLOSE flag in CreateFile call above.
1350     CloseHandle(fh);
1351     fh = NULL;
1352     return NULL;
1353   } else {
1354     // We created the file mapping, but rarely the size of the
1355     // backing store file is reported as zero (0) which can cause
1356     // failures when trying to use the hsperfdata file.
1357     struct stat statbuf;
1358     int ret_code = ::stat(filename, &statbuf);
1359     if (ret_code == OS_ERR) {
1360       if (PrintMiscellaneous && Verbose) {
1361         warning("could not stat file %s: %d\n", filename, ret_code);
1362       }
1363       CloseHandle(fmh);
1364       CloseHandle(fh);
1365       fh = NULL;
1366       fmh = NULL;
1367       return NULL;
1368     }
1369 
1370     // We could always call FlushFileBuffers() but the Microsoft
1371     // docs indicate that it is considered expensive so we only
1372     // call it when we observe the size as zero (0).
1373     if (statbuf.st_size == 0 && FlushFileBuffers(fh) != TRUE) {
1374       DWORD lasterror = GetLastError();
1375       if (PrintMiscellaneous && Verbose) {
1376         warning("could not flush file %s: %d\n", filename, lasterror);
1377       }
1378       CloseHandle(fmh);
1379       CloseHandle(fh);
1380       fh = NULL;
1381       fmh = NULL;
1382       return NULL;
1383     }
1384   }
1385 
1386   // the file has been successfully created and the file mapping
1387   // object has been created.
1388   sharedmem_fileHandle = fh;
1389   sharedmem_fileName = strdup(filename);
1390 
1391   return fmh;
1392 }
1393 
1394 // open the shared memory object for the given vmid.
1395 //
1396 static HANDLE open_sharedmem_object(const char* objectname, DWORD ofm_access, TRAPS) {
1397 
1398   HANDLE fmh;
1399 
1400   // open the file mapping with the requested mode
1401   fmh = OpenFileMapping(
1402                ofm_access,       /* DWORD access mode */
1403                FALSE,            /* BOOL inherit flag - Do not allow inherit */
1404                objectname);      /* name for object */
1405