Skip to content

Conversation

@Ashp116
Copy link

@Ashp116 Ashp116 commented Nov 20, 2025

Description

This PR fixes the issue of reading process stats when the process is not found. Although there is a check before to check if the process exists, there are chances when the process gets killed between each check. The previous implementation takes the raw file content and parses it, disregarding OSErrors. This PR adds security to ensure safe resolution of OSError to get process info.

Logs

Here is the jtop.service logs.

Nov 20 03:06:15 jetson jtop[3648]: [CRITICAL] jtop.core.timer_reader - Exception in 'timer_reader thread': [Errno 2] No such file or directory: '/proc/24335/stat'
Nov 20 03:06:16 jetson jtop[3648]: [WARNING] jtop.service - FileNotFoundError on service thread
Nov 20 03:06:16 jetson jtop[3648]: Process JtopServer-1:
Nov 20 03:06:16 jetson jtop[3648]: Traceback (most recent call last):
Nov 20 03:06:16 jetson jtop[3648]:   File "/usr/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap
Nov 20 03:06:16 jetson jtop[3648]:     self.run()
Nov 20 03:06:16 jetson jtop[3648]:   File "/usr/local/lib/python3.10/dist-packages/jtop/service.py", line 529, in run
Nov 20 03:06:16 jetson jtop[3648]:     if self._timer_reader.close(timeout=TIMEOUT_SWITCHOFF):
Nov 20 03:06:16 jetson jtop[3648]:   File "/usr/local/lib/python3.10/dist-packages/jtop/core/timer_reader.py", line 75, in close
Nov 20 03:06:16 jetson jtop[3648]:     self._error_status()
Nov 20 03:06:16 jetson jtop[3648]:   File "/usr/local/lib/python3.10/dist-packages/jtop/core/timer_reader.py", line 90, in _error_status
Nov 20 03:06:16 jetson jtop[3648]:     raise ex_value
Nov 20 03:06:16 jetson jtop[3648]:   File "/usr/local/lib/python3.10/dist-packages/jtop/core/timer_reader.py", line 46, in _timer_callback
Nov 20 03:06:16 jetson jtop[3648]:     self._callback()
Nov 20 03:06:16 jetson jtop[3648]:   File "/usr/local/lib/python3.10/dist-packages/jtop/service.py", line 668, in jtop_stats
Nov 20 03:06:16 jetson jtop[3648]:     data = self.jtop_decode()
Nov 20 03:06:16 jetson jtop[3648]:   File "/usr/local/lib/python3.10/dist-packages/jtop/service.py", line 632, in jtop_decode
Nov 20 03:06:16 jetson jtop[3648]:     total, table = self.processes.get_status()
Nov 20 03:06:16 jetson jtop[3648]:   File "/usr/local/lib/python3.10/dist-packages/jtop/core/processes.py", line 136, in get_status
Nov 20 03:06:16 jetson jtop[3648]:     table = [self.get_process_info(prc[0], prc[3], prc[2], uptime) for prc in table]
Nov 20 03:06:16 jetson jtop[3648]:   File "/usr/local/lib/python3.10/dist-packages/jtop/core/processes.py", line 136, in <listcomp>
Nov 20 03:06:16 jetson jtop[3648]:     table = [self.get_process_info(prc[0], prc[3], prc[2], uptime) for prc in table]
Nov 20 03:06:16 jetson jtop[3648]:   File "/usr/local/lib/python3.10/dist-packages/jtop/core/processes.py", line 92, in get_process_info
Nov 20 03:06:16 jetson jtop[3648]:     stat = cat(os.path.join('/proc', pid, 'stat')).split()
Nov 20 03:06:16 jetson jtop[3648]:   File "/usr/local/lib/python3.10/dist-packages/jtop/core/common.py", line 115, in cat
Nov 20 03:06:16 jetson jtop[3648]:     with open(path, 'r') as f:
Nov 20 03:06:16 jetson jtop[3648]: FileNotFoundError: [Errno 2] No such file or directory: '/proc/24335/stat'

Summary by Sourcery

Handle missing or removed processes gracefully by catching file errors when reading /proc files and skipping stats for processes that vanish between checks

Bug Fixes:

  • Catch OSError in common.cat() and return None when proc files are unavailable
  • Add None checks in get_process_info for stat, loginuid, and statm reads to skip missing processes

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Nov 20, 2025

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

This PR adds robust error handling to file reads in the proc-based process stats path. The common.cat helper now catches OSError and returns None, and get_process_info in processes.py checks for None on stat, loginuid, and statm reads, bailing out early with an empty result when a proc file is missing to prevent uncaught exceptions.

Class diagram for updated process info retrieval

classDiagram
    class Processes {
        +get_process_info(pid, gpu_mem_usage, process_name, uptime)
        usernames: dict
    }
    class Common {
        +cat(path)
    }
    Processes --> Common : uses
    Processes : +get_process_info checks for None from cat()
    Common : +cat returns None on OSError
Loading

Flow diagram for robust process info retrieval with error handling

flowchart TD
    A["get_process_info() called"] --> B["Check if /proc/<pid> exists"]
    B -->|exists| C["Read /proc/<pid>/stat with cat()"]
    C -->|cat returns None| Z["Return [] (bail out)"]
    C -->|cat returns value| D["Read /proc/<pid>/loginuid with cat()"]
    D -->|cat returns None| Z
    D -->|cat returns value| E["Read /proc/<pid>/statm with cat()"]
    E -->|cat returns None| Z
    E -->|cat returns value| F["Parse and return process info"]
    B -->|does not exist| Z
Loading

File-Level Changes

Change Details Files
Handle OSError in common.cat by returning None
  • Wrap the file open/read in a try/except block
  • Return None when an OSError occurs
jtop/core/common.py
Guard get_process_info against missing proc files
  • Assign stat read to a variable and return [] if None before splitting
  • Assign loginuid read to a variable and return [] if None before int conversion
  • Check statm read for None and return [] before splitting
jtop/core/processes.py

Possibly linked issues

  • #JP5.1.2: The PR fixes the 'No such process' error in jtop by safely handling OS errors when reading process stats.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • The repeated None checks after each cat invocation could be consolidated into a helper or decorator to reduce boilerplate and improve readability.
  • Silently returning an empty list when a proc file is missing might hide intermittent failures; consider adding a debug log when skipping a process to aid troubleshooting.
  • The cat function currently catches all OSError exceptions—restricting that to FileNotFoundError (or using a custom exception) would avoid masking other file-related errors.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The repeated None checks after each cat invocation could be consolidated into a helper or decorator to reduce boilerplate and improve readability.
- Silently returning an empty list when a proc file is missing might hide intermittent failures; consider adding a debug log when skipping a process to aid troubleshooting.
- The cat function currently catches all OSError exceptions—restricting that to FileNotFoundError (or using a custom exception) would avoid masking other file-related errors.

## Individual Comments

### Comment 1
<location> `jtop/core/processes.py:108` </location>
<code_context>
         # VmRSS is the resident set size of the process, which is the portion of the process's memory
         # that is held in RAM and is not swapped out to disk. This is the amount of memory that the process is currently using.
         mem_raw = cat(os.path.join('/proc', pid, 'statm')).split()
+        if mem_raw is None:
+            return []
         vm_rss = int(mem_raw[1]) * 4
</code_context>

<issue_to_address>
**issue:** Check for empty list after split to avoid IndexError.

If mem_raw is empty, accessing mem_raw[1] will cause an IndexError. Please check the list length before accessing its elements.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant