Skip to content

Commit 500499d

Browse files
committed
Merge branch 'develop'
2 parents 1212756 + 095b999 commit 500499d

18 files changed

+144
-47
lines changed

Diff for: .github/ISSUE_TEMPLATE/bug-report.md

+11-3
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,16 @@ journalctl -u jtop.service -n 100 --no-pager
5858

5959
### Log from jetson-stats installation
6060

61-
Attach here the output from: `sudo -H pip3 install --no-cache-dir -U jetson-stats`
61+
Attach here the output from: `sudo -H pip3 install --no-cache-dir -v -U jetson-stats`
6262

6363
<!-- Use:
64-
sudo -H pip3 install --no-cache-dir -U jetson-stats
65-
-->
64+
sudo -H pip3 install --no-cache-dir -v -U jetson-stats
65+
-->
66+
67+
### RAW Data
68+
69+
File from `jtop --error-log` attached
70+
71+
<!-- Please attach the output from:
72+
jtop --error-log
73+
-->

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
_build/
66
dist/
77
doc/
8+
build/
89

910
# Python egg metadata, regenerated from source files by setuptools.
1011
/*.egg-info

Diff for: docs/jtop/jtop.rst

+27
Original file line numberDiff line numberDiff line change
@@ -304,3 +304,30 @@ INFO
304304
This page show all technical information about your board. This output is available :py:attr:`jtop.jtop.board`.
305305

306306
Compare all previous versions, now the Serial number is hidden and you can enable only clicking on the area or pressing the key **s**.
307+
308+
Uninstall
309+
---------
310+
311+
For a complete and *manual* uninstall of this package on your device there are few steps to do
312+
313+
.. warning::
314+
315+
You need **super user** to execute the commands
316+
317+
.. code-block:: bash
318+
319+
# Stop, disable and remove jtop.service
320+
systemctl stop jtop.service
321+
systemctl disable jtop.service
322+
rm /etc/systemd/system/jtop.service
323+
# reload services
324+
systemctl daemon-reload
325+
326+
# remove jtop pipe
327+
rm /run/jtop.sock
328+
329+
# Remove enviroment variables
330+
rm /etc/profile.d/jtop_env.sh
331+
332+
# Uninstall python package
333+
pip3 uninstall jetson-stats

Diff for: docs/troubleshooting.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ Before to open an `issue`_, try to reinstall the latest version with this comman
9797

9898
.. code-block:: bash
9999
100-
sudo pip3 install --no-cache-dir -U jetson-stats
100+
sudo pip3 install --no-cache-dir -v -U jetson-stats
101101
102102
Save the output somewhere, if this command doesn't fix can be helpful when you one an `issue`_.
103103

Diff for: jtop/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,5 @@
3131
__copyright__ = "(c) 2024, Raffaello Bonghi"
3232
# Version package
3333
# https://packaging.python.org/guides/distributing-packages-using-setuptools/#choosing-a-versioning-scheme
34-
__version__ = "4.2.4"
34+
__version__ = "4.2.5"
3535
# EOF

Diff for: jtop/__main__.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import signal
2020
import os
2121
import sys
22-
import locale
22+
# import locale
2323
import argparse
2424
# control command line
2525
import curses
@@ -94,8 +94,6 @@ def main():
9494
# Initialize signals
9595
# signal.signal(signal.SIGINT, exit_signal) # Do not needed equivalent to exception KeyboardInterrupt
9696
signal.signal(signal.SIGTERM, exit_signal)
97-
# https://stackoverflow.com/questions/56373360/n-curses-within-python-how-to-catch-and-print-non-ascii-character
98-
locale.setlocale(locale.LC_ALL, '')
9997
# Run jtop service
10098
if os.getenv('JTOP_SERVICE', False):
10199
# Initialize logging level
@@ -142,6 +140,9 @@ def main():
142140
sys.exit(0)
143141
# jtop client start
144142
try:
143+
# https://stackoverflow.com/questions/56373360/n-curses-within-python-how-to-catch-and-print-non-ascii-character
144+
# Commented for issues #466 #393
145+
# locale.setlocale(locale.LC_ALL, '')
145146
# Open jtop client
146147
with jtop(interval=interval) as jetson:
147148
# Call the curses wrapper

Diff for: jtop/core/engine.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def read_engine(path):
5555

5656
class EngineService(object):
5757

58-
ENGINES = ['ape', 'dla', 'pva', 'vic', 'nvjpg', 'nvenc', 'nvdec', 'se.', 'cvnas', 'msenc']
58+
ENGINES = ['ape', 'dla', 'pva', 'vic', 'nvjpg', 'nvenc', 'nvdec', 'se.', 'cvnas', 'msenc', 'ofa']
5959

6060
def __init__(self):
6161
# Sort list before start

Diff for: jtop/core/gpu.py

+19-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
from .command import Command
2424
# Create logger
2525
logger = logging.getLogger(__name__)
26+
# default ipgu path for Jetson devices
27+
DEFAULT_IGPU_PATH = "/sys/class/devfreq/"
2628

2729

2830
def check_nvidia_smi():
@@ -95,6 +97,22 @@ def igpu_read_status(path):
9597
return gpu
9698

9799

100+
def get_raw_igpu_devices():
101+
igpu_path = DEFAULT_IGPU_PATH
102+
raw_output = {}
103+
for item in os.listdir(igpu_path):
104+
item_path = os.path.join(igpu_path, item)
105+
if os.path.isfile(item_path) or os.path.islink(item_path):
106+
# Check name device
107+
name_path = "{item}/device/of_node/name".format(item=item_path)
108+
if os.path.isfile(name_path):
109+
# Decode name
110+
name = cat(name_path)
111+
# path and file
112+
raw_output[name_path] = "{}".format(name)
113+
return raw_output
114+
115+
98116
def find_igpu(igpu_path):
99117
# Check if exist a integrated gpu
100118
# if not os.path.exists("/dev/nvhost-gpu") and not os.path.exists("/dev/nvhost-power-gpu"):
@@ -260,7 +278,7 @@ class GPUService(object):
260278

261279
def __init__(self):
262280
# Detect integrated GPU
263-
igpu_path = "/sys/class/devfreq/"
281+
igpu_path = DEFAULT_IGPU_PATH
264282
if os.getenv('JTOP_TESTING', False):
265283
igpu_path = "/fake_sys/class/devfreq/"
266284
logger.warning("Running in JTOP_TESTING folder={root_dir}".format(root_dir=igpu_path))

Diff for: jtop/core/jetson_libraries.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
FileNotFoundError = IOError
2727

2828

29-
MODULES = ['cuDNN', 'TensorRT', 'VPI'] # 'Visionworks'
29+
MODULES = ['cuDNN', 'TensorRT.', 'VPI'] # 'Visionworks'
3030
CUDA_FILE_RE = re.compile(r'CUDA Version (.*)')
3131
CUDA_NVCC_RE = re.compile(r'V([0-9]+.[0-9]+.[0-9]+)')
3232

@@ -100,17 +100,24 @@ def get_libraries():
100100
# Find all modules
101101
modules = get_all_modules()
102102
for name in MODULES:
103-
os_variables[name] = ''
103+
# Fix TensorRT search #462
104+
name_dict = name[:-1] if name.endswith('.') else name
105+
os_variables[name_dict] = ''
104106
# Find version if installed
105107
for module, version in modules.items():
108+
if name.endswith('.') and name.lower()[:-1] == module:
109+
os_variables[name_dict] = version.split('-')[0]
110+
break
106111
if name.lower() in module:
107-
os_variables[name] = version.split('-')[0]
112+
os_variables[name_dict] = version.split('-')[0]
108113
break
109114
# Get Vulkan output
110115
cmd_vulkaninfo = Command(['which', 'vulkaninfo'])
111116
try:
112117
lines = cmd_vulkaninfo()
113118
# Extract version
119+
if not lines:
120+
raise Command.CommandException("Missing command", -3)
114121
cmd_vulkan = Command(lines)
115122
lines = cmd_vulkan()
116123
for line in lines:

Diff for: jtop/core/jetson_variables.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ def read_i2c_raw_data(bus, registry, size_block):
177177
return string_data
178178

179179

180-
def get_raw_output():
180+
def get_jetson_raw_output():
181181
raw_output = {}
182182
# Catch all output from all files
183183
for file in RAW_FILES:

Diff for: jtop/core/memory.py

+19-11
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import subprocess as sp
2525
from .processes import read_process_table
2626
from .engine import read_engine
27-
from .common import cat, check_file, GenericInterface
27+
from .common import cat, GenericInterface
2828
from .command import Command
2929
# Create logger
3030
logger = logging.getLogger(__name__)
@@ -184,6 +184,20 @@ def read_emc(root_path):
184184
if 'max' in emc:
185185
if emc_cap > 0 and emc_cap < emc['max']:
186186
emc['max'] = emc_cap
187+
# Percentage utilization
188+
# https://forums.developer.nvidia.com/t/real-time-emc-bandwidth-with-sysfs/107479/3
189+
if os.access(root_path + "/debug/cactmon/mc_all", os.R_OK):
190+
with open(root_path + "/debug/cactmon/mc_all", 'r') as f:
191+
utilization = int(f.read())
192+
elif os.access(root_path + "/actmon_avg_activity/mc_all", os.R_OK):
193+
with open(root_path + "/actmon_avg_activity/mc_all", 'r') as f:
194+
utilization = int(f.read())
195+
else:
196+
# if utilization not accesibile return empty EMC data
197+
return {}
198+
emc['val'] = utilization // emc['cur']
199+
# Set always online this engine
200+
emc['online'] = True
187201
return emc
188202

189203

@@ -289,6 +303,9 @@ def __init__(self, config):
289303
self._is_emc = True if read_emc(self._root_path) else False
290304
if self._is_emc:
291305
logger.info("Found EMC!")
306+
self._is_iram = os.path.isdir(self._root_path + "/debug/nvmap/iram")
307+
if self._is_iram:
308+
logger.info("Found IRAM!")
292309
# Initialization memory
293310
logger.info("Memory service started")
294311

@@ -421,17 +438,8 @@ def get_status(self, mem_total):
421438
# Read EMC status
422439
if self._is_emc:
423440
memory['EMC'] = read_emc(self._root_path)
424-
# Set always online this engine
425-
memory['EMC']['online'] = True
426-
# Percentage utilization
427-
# https://forums.developer.nvidia.com/t/real-time-emc-bandwidth-with-sysfs/107479/3
428-
if check_file(self._root_path + "/debug/cactmon/mc_all"):
429-
utilization = int(cat(self._root_path + "/debug/cactmon/mc_all"))
430-
else:
431-
utilization = int(cat(self._root_path + "/actmon_avg_activity/mc_all"))
432-
memory['EMC']['val'] = utilization // memory['EMC']['cur']
433441
# Read IRAM if available
434-
if os.path.isdir(self._root_path + "/debug/nvmap/iram"):
442+
if self._is_iram:
435443
size = 0
436444
if os.path.isfile(self._root_path + "/debug/nvmap/iram/size"):
437445
# Convert from Hex to decimal - Number in bytes

Diff for: jtop/core/nvpmodel.py

+2
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ def nvpmodel_query():
7474
lines = nvpmodel_p(timeout=COMMAND_TIMEOUT)
7575
except FileNotFoundError:
7676
raise JtopException("nvpmodel doesn't exist")
77+
except Command.CommandException:
78+
raise JtopException("nvpmodel command unavailable")
7779
# Extract lines
7880
for idx, line in enumerate(lines):
7981
# Search configuration NVPmodel

Diff for: jtop/core/temperature.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,9 @@ def read_temperature(data):
3333
try:
3434
value = float(cat(path)) / 1000.0
3535
values[name] = value
36-
except OSError:
36+
except (OSError, ValueError):
3737
# If negative sensor offline
3838
values[name] = TEMPERATURE_OFFLINE
39-
except ValueError:
40-
values[name] = TEMPERATURE_OFFLINE
4139
return values
4240

4341

Diff for: jtop/github.py

+13-6
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@
2121

2222
from copy import deepcopy
2323
# jtop variable
24+
from .core.gpu import get_raw_igpu_devices
2425
from .core.hardware import get_platform_variables
25-
from .core.jetson_variables import get_raw_output
26+
from .core.jetson_variables import get_jetson_raw_output
2627
from .terminal_colors import bcolors
2728

2829

@@ -79,12 +80,18 @@ def get_hardware_log():
7980
body = "--------------------- PLATFORM -------------------------\n"
8081
for name, value in platform.items():
8182
body += "{name}: {value}\n".format(name=name, value=value)
82-
# Print all raw output
83-
raw_output = get_raw_output()
84-
body += "-------------------- RAW OUTPUT ------------------------"
83+
# Print all jetson raw output
84+
raw_output = get_jetson_raw_output()
85+
body += "-------------------- JETSON RAW OUTPUT -----------------\n"
8586
for name, value in raw_output.items():
86-
body += "\n------------------\n"
87-
body += "{name}:\n{value}".format(name=name, value=value)
87+
body += "------------------\n"
88+
body += "Path: {name}\n{value}\n".format(name=name, value=value)
89+
# Print device list
90+
raw_output = get_raw_igpu_devices()
91+
body += "\n-------------------- IGPU OUTPUT ---------------------\n"
92+
for path, value in raw_output.items():
93+
body += "------------------\n"
94+
body += "Path: {path}\n{value}\n".format(path=path, value=value)
8895
return body
8996

9097

Diff for: jtop/gui/lib/process_table.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ def __init__(self, stdscr, jetson):
4444
self.type_reverse = True
4545

4646
def draw(self, pos_y, pos_x, width, height, key, mouse):
47-
processes = self.jetson.processes
4847
# Plot low bar background line
4948
try:
5049
self.stdscr.addstr(pos_y, 0, " " * width, NColors.igreen())
@@ -67,7 +66,11 @@ def draw(self, pos_y, pos_x, width, height, key, mouse):
6766
except curses.error:
6867
break
6968
# Sort table for selected line
70-
sorted_processes = sorted(processes, key=lambda x: x[self.line_sort], reverse=self.type_reverse)
69+
try:
70+
sorted_processes = self.jetson.processes
71+
sorted_processes = sorted(sorted_processes, key=lambda x: x[self.line_sort], reverse=self.type_reverse)
72+
except IndexError:
73+
pass
7174
# Draw all processes
7275
# Instantiate the number of process variable to avoid an unbound local error if the process table is empty.
7376
nprocess = 0

Diff for: jtop/jetson_config.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@
3737
# Detect user
3838
user = os.environ.get('USER', '')
3939
# Get user from sudo
40-
if 'SUDO_USER' in os.environ:
41-
user = os.environ['SUDO_USER']
40+
sudo_user = os.environ.get('SUDO_USER', '')
41+
# If are both empty assign 'root'
42+
user = sudo_user or 'root'
4243
# Locate folder and type of installation
4344
folder, _ = os.path.split(__file__)
4445
folder = os.path.dirname(folder)

0 commit comments

Comments
 (0)