Bug 999473 - report number of open file descriptions (fd) in about:memory. r=njn

This commit is contained in:
Eric Rahm 2014-04-25 13:00:15 -07:00
Родитель ca2a2308b2
Коммит 41bcb2678a
1 изменённых файлов: 86 добавлений и 0 удалений

Просмотреть файл

@ -275,6 +275,14 @@ private:
break;
}
fclose(f);
// Report the open file descriptors for this process.
nsPrintfCString procFdPath("/proc/%s/fd", pidStr);
nsresult rv = CollectOpenFileReports(
aHandleReport, aData, procFdPath, processName);
if (NS_FAILED(rv)) {
break;
}
}
}
closedir(d);
@ -723,6 +731,84 @@ private:
return NS_OK;
}
nsresult
CollectOpenFileReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData,
const nsACString& aProcPath,
const nsACString& aProcessName)
{
// All file descriptors opened by a process are listed under
// /proc/<pid>/fd/<numerical_fd>. Each entry is a symlink that points to the
// path that was opened. This can be an actual file, a socket, a pipe, an
// anon_inode, or possibly an uncategorized device.
const char kFilePrefix[] = "/";
const char kSocketPrefix[] = "socket:";
const char kPipePrefix[] = "pipe:";
const char kAnonInodePrefix[] = "anon_inode:";
const nsCString procPath(aProcPath);
DIR* d = opendir(procPath.get());
if (!d) {
if (NS_WARN_IF(errno != ENOENT && errno != EACCES)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
char linkPath[PATH_MAX + 1];
struct dirent* ent;
while ((ent = readdir(d))) {
const char* fd = ent->d_name;
// Skip "." and ".." (and any other dotfiles).
if (fd[0] == '.') {
continue;
}
nsPrintfCString fullPath("%s/%s", procPath.get(), fd);
ssize_t linkPathSize = readlink(fullPath.get(), linkPath, PATH_MAX);
if (linkPathSize > 0) {
linkPath[linkPathSize] = '\0';
#define CHECK_PREFIX(prefix) \
(strncmp(linkPath, prefix, sizeof(prefix) - 1) == 0)
const char* category = nullptr;
const char* descriptionPrefix = nullptr;
if (CHECK_PREFIX(kFilePrefix)) {
category = "files"; // No trailing slash, the file path will have one
descriptionPrefix = "An open";
} else if (CHECK_PREFIX(kSocketPrefix)) {
category = "sockets/";
descriptionPrefix = "A socket";
} else if (CHECK_PREFIX(kPipePrefix)) {
category = "pipes/";
descriptionPrefix = "A pipe";
} else if (CHECK_PREFIX(kAnonInodePrefix)) {
category = "anon_inodes/";
descriptionPrefix = "An anon_inode";
} else {
category = "";
descriptionPrefix = "An uncategorized";
}
#undef CHECK_PREFIX
const nsCString processName(aProcessName);
nsPrintfCString entryPath(
"open-fds/%s/%s%s/%s", processName.get(), category, linkPath, fd);
nsPrintfCString entryDescription(
"%s file descriptor opened by the process", descriptionPrefix);
REPORT_WITH_CLEANUP(
entryPath, UNITS_COUNT, 1, entryDescription, closedir(d));
}
}
closedir(d);
return NS_OK;
}
#undef REPORT
};