OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2013 The Chromium Authors. All rights reserved. | 2 # Copyright 2013 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 # A Python library to read and store procfs (/proc) information on Linux. | 6 # A Python library to read and store procfs (/proc) information on Linux. |
7 # | 7 # |
8 # Each information storage class in this file stores original data as original | 8 # Each information storage class in this file stores original data as original |
9 # as reasonablly possible. Translation is done when requested. It is to make it | 9 # as reasonablly possible. Translation is done when requested. It is to make it |
10 # always possible to probe the original data. | 10 # always possible to probe the original data. |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 def load_file(stat_f): | 85 def load_file(stat_f): |
86 raw = stat_f.readlines() | 86 raw = stat_f.readlines() |
87 stat = ProcStat._PATTERN.match(raw[0]) | 87 stat = ProcStat._PATTERN.match(raw[0]) |
88 return ProcStat(raw, | 88 return ProcStat(raw, |
89 stat.groupdict().get('PID'), | 89 stat.groupdict().get('PID'), |
90 stat.groupdict().get('VSIZE'), | 90 stat.groupdict().get('VSIZE'), |
91 stat.groupdict().get('RSS')) | 91 stat.groupdict().get('RSS')) |
92 | 92 |
93 @staticmethod | 93 @staticmethod |
94 def load(pid): | 94 def load(pid): |
95 with open(os.path.join('/proc', str(pid), 'stat'), 'r') as stat_f: | 95 try: |
96 return ProcStat.load_file(stat_f) | 96 with open(os.path.join('/proc', str(pid), 'stat'), 'r') as stat_f: |
| 97 return ProcStat.load_file(stat_f) |
| 98 except IOError: |
| 99 return None |
97 | 100 |
98 @property | 101 @property |
99 def raw(self): | 102 def raw(self): |
100 return self._raw | 103 return self._raw |
101 | 104 |
102 @property | 105 @property |
103 def pid(self): | 106 def pid(self): |
104 return int(self._pid) | 107 return int(self._pid) |
105 | 108 |
106 @property | 109 @property |
(...skipping 21 matching lines...) Expand all Loading... |
128 self._size = size | 131 self._size = size |
129 self._resident = resident | 132 self._resident = resident |
130 self._share = share | 133 self._share = share |
131 self._text = text | 134 self._text = text |
132 self._lib = lib | 135 self._lib = lib |
133 self._data = data | 136 self._data = data |
134 self._dt = dt | 137 self._dt = dt |
135 | 138 |
136 @staticmethod | 139 @staticmethod |
137 def load_file(statm_f): | 140 def load_file(statm_f): |
138 raw = statm_f.readlines() | 141 try: |
| 142 raw = statm_f.readlines() |
| 143 except (IOError, OSError): |
| 144 return None |
139 statm = ProcStatm._PATTERN.match(raw[0]) | 145 statm = ProcStatm._PATTERN.match(raw[0]) |
140 return ProcStatm(raw, | 146 return ProcStatm(raw, |
141 statm.groupdict().get('SIZE'), | 147 statm.groupdict().get('SIZE'), |
142 statm.groupdict().get('RESIDENT'), | 148 statm.groupdict().get('RESIDENT'), |
143 statm.groupdict().get('SHARE'), | 149 statm.groupdict().get('SHARE'), |
144 statm.groupdict().get('TEXT'), | 150 statm.groupdict().get('TEXT'), |
145 statm.groupdict().get('LIB'), | 151 statm.groupdict().get('LIB'), |
146 statm.groupdict().get('DATA'), | 152 statm.groupdict().get('DATA'), |
147 statm.groupdict().get('DT')) | 153 statm.groupdict().get('DT')) |
148 | 154 |
149 @staticmethod | 155 @staticmethod |
150 def load(pid): | 156 def load(pid): |
151 with open(os.path.join('/proc', str(pid), 'statm'), 'r') as statm_f: | 157 try: |
152 return ProcStatm.load_file(statm_f) | 158 with open(os.path.join('/proc', str(pid), 'statm'), 'r') as statm_f: |
| 159 return ProcStatm.load_file(statm_f) |
| 160 except (IOError, OSError): |
| 161 return None |
153 | 162 |
154 @property | 163 @property |
155 def raw(self): | 164 def raw(self): |
156 return self._raw | 165 return self._raw |
157 | 166 |
158 @property | 167 @property |
159 def size(self): | 168 def size(self): |
160 return int(self._size) | 169 return int(self._size) |
161 | 170 |
162 @property | 171 @property |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 | 332 |
324 @staticmethod | 333 @staticmethod |
325 def load_file(maps_f): | 334 def load_file(maps_f): |
326 table = ProcMaps() | 335 table = ProcMaps() |
327 for line in maps_f: | 336 for line in maps_f: |
328 table.append_line(line) | 337 table.append_line(line) |
329 return table | 338 return table |
330 | 339 |
331 @staticmethod | 340 @staticmethod |
332 def load(pid): | 341 def load(pid): |
333 with open(os.path.join('/proc', str(pid), 'maps'), 'r') as maps_f: | 342 try: |
334 return ProcMaps.load_file(maps_f) | 343 with open(os.path.join('/proc', str(pid), 'maps'), 'r') as maps_f: |
| 344 return ProcMaps.load_file(maps_f) |
| 345 except (IOError, OSError): |
| 346 return None |
335 | 347 |
336 def append_line(self, line): | 348 def append_line(self, line): |
337 entry = self.parse_line(line) | 349 entry = self.parse_line(line) |
338 if entry: | 350 if entry: |
339 self._append_entry(entry) | 351 self._append_entry(entry) |
340 return entry | 352 return entry |
341 | 353 |
342 @staticmethod | 354 @staticmethod |
343 def parse_line(line): | 355 def parse_line(line): |
344 matched = ProcMaps.MAPS_PATTERN.match(line) | 356 matched = ProcMaps.MAPS_PATTERN.match(line) |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 | 560 |
549 @staticmethod | 561 @staticmethod |
550 def load(pid, maps): | 562 def load(pid, maps): |
551 total_present = 0 | 563 total_present = 0 |
552 total_swapped = 0 | 564 total_swapped = 0 |
553 total_vsize = 0 | 565 total_vsize = 0 |
554 in_process_dup = 0 | 566 in_process_dup = 0 |
555 vma_internals = collections.OrderedDict() | 567 vma_internals = collections.OrderedDict() |
556 process_pageframe_set = set() | 568 process_pageframe_set = set() |
557 | 569 |
558 pagemap_fd = os.open( | 570 try: |
559 os.path.join('/proc', str(pid), 'pagemap'), os.O_RDONLY) | 571 pagemap_fd = os.open( |
| 572 os.path.join('/proc', str(pid), 'pagemap'), os.O_RDONLY) |
| 573 except (IOError, OSError): |
| 574 return None |
560 for vma in maps: | 575 for vma in maps: |
561 present = 0 | 576 present = 0 |
562 swapped = 0 | 577 swapped = 0 |
563 vsize = 0 | 578 vsize = 0 |
564 pageframes = collections.defaultdict(int) | 579 pageframes = collections.defaultdict(int) |
565 begin_offset = ProcPagemap._offset(vma.begin) | 580 begin_offset = ProcPagemap._offset(vma.begin) |
566 chunk_size = ProcPagemap._offset(vma.end) - begin_offset | 581 chunk_size = ProcPagemap._offset(vma.end) - begin_offset |
567 os.lseek(pagemap_fd, begin_offset, os.SEEK_SET) | 582 try: |
568 buf = os.read(pagemap_fd, chunk_size) | 583 os.lseek(pagemap_fd, begin_offset, os.SEEK_SET) |
| 584 buf = os.read(pagemap_fd, chunk_size) |
| 585 except (IOError, OSError): |
| 586 return None |
569 if len(buf) < chunk_size: | 587 if len(buf) < chunk_size: |
570 _LOGGER.warn('Failed to read pagemap at 0x%x in %d.' % (vma.begin, pid)) | 588 _LOGGER.warn('Failed to read pagemap at 0x%x in %d.' % (vma.begin, pid)) |
571 pagemap_values = struct.unpack( | 589 pagemap_values = struct.unpack( |
572 '=%dQ' % (len(buf) / ProcPagemap._BYTES_PER_PAGEMAP_VALUE), buf) | 590 '=%dQ' % (len(buf) / ProcPagemap._BYTES_PER_PAGEMAP_VALUE), buf) |
573 for pagemap_value in pagemap_values: | 591 for pagemap_value in pagemap_values: |
574 vsize += ProcPagemap._BYTES_PER_OS_PAGE | 592 vsize += ProcPagemap._BYTES_PER_OS_PAGE |
575 if pagemap_value & ProcPagemap._MASK_PRESENT: | 593 if pagemap_value & ProcPagemap._MASK_PRESENT: |
576 if (pagemap_value & ProcPagemap._MASK_PFN) in process_pageframe_set: | 594 if (pagemap_value & ProcPagemap._MASK_PFN) in process_pageframe_set: |
577 in_process_dup += ProcPagemap._BYTES_PER_OS_PAGE | 595 in_process_dup += ProcPagemap._BYTES_PER_OS_PAGE |
578 else: | 596 else: |
579 process_pageframe_set.add(pagemap_value & ProcPagemap._MASK_PFN) | 597 process_pageframe_set.add(pagemap_value & ProcPagemap._MASK_PFN) |
580 if (pagemap_value & ProcPagemap._MASK_PFN) not in pageframes: | 598 if (pagemap_value & ProcPagemap._MASK_PFN) not in pageframes: |
581 present += ProcPagemap._BYTES_PER_OS_PAGE | 599 present += ProcPagemap._BYTES_PER_OS_PAGE |
582 pageframes[pagemap_value & ProcPagemap._MASK_PFN] += 1 | 600 pageframes[pagemap_value & ProcPagemap._MASK_PFN] += 1 |
583 if pagemap_value & ProcPagemap._MASK_SWAPPED: | 601 if pagemap_value & ProcPagemap._MASK_SWAPPED: |
584 swapped += ProcPagemap._BYTES_PER_OS_PAGE | 602 swapped += ProcPagemap._BYTES_PER_OS_PAGE |
585 vma_internals[vma] = ProcPagemap.VMA(vsize, present, swapped, pageframes) | 603 vma_internals[vma] = ProcPagemap.VMA(vsize, present, swapped, pageframes) |
586 total_present += present | 604 total_present += present |
587 total_swapped += swapped | 605 total_swapped += swapped |
588 total_vsize += vsize | 606 total_vsize += vsize |
589 os.close(pagemap_fd) | 607 try: |
| 608 os.close(pagemap_fd) |
| 609 except OSError: |
| 610 return None |
590 | 611 |
591 return ProcPagemap(total_vsize, total_present, total_swapped, | 612 return ProcPagemap(total_vsize, total_present, total_swapped, |
592 vma_internals, in_process_dup) | 613 vma_internals, in_process_dup) |
593 | 614 |
594 @staticmethod | 615 @staticmethod |
595 def _offset(virtual_address): | 616 def _offset(virtual_address): |
596 return virtual_address / ProcPagemap._VIRTUAL_TO_PAGEMAP_OFFSET | 617 return virtual_address / ProcPagemap._VIRTUAL_TO_PAGEMAP_OFFSET |
597 | 618 |
598 @property | 619 @property |
599 def vsize(self): | 620 def vsize(self): |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
720 print ' status: %d (Peak:%d)' % (procs[pid].status.vm_rss * 1024, | 741 print ' status: %d (Peak:%d)' % (procs[pid].status.vm_rss * 1024, |
721 procs[pid].status.vm_hwm * 1024) | 742 procs[pid].status.vm_hwm * 1024) |
722 print ' smaps: %d' % (procs[pid].smaps.rss * 1024) | 743 print ' smaps: %d' % (procs[pid].smaps.rss * 1024) |
723 print 'pagemap: %d' % procs[pid].pagemap.present | 744 print 'pagemap: %d' % procs[pid].pagemap.present |
724 | 745 |
725 return 0 | 746 return 0 |
726 | 747 |
727 | 748 |
728 if __name__ == '__main__': | 749 if __name__ == '__main__': |
729 sys.exit(main(sys.argv)) | 750 sys.exit(main(sys.argv)) |
OLD | NEW |