Skip to contentSkip to conversation

usertools/dpdk-telemetry: print name of app when connected

PATCH Superseded Bruce Richardson 4 participants 8 messages Feb 16, 2021 – Mar 25, 2021

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 usertools/dpdk-telemetry: print name of app when connected

When the dpdk-telemetry client connects to a DPDK instance, we can use the PID provided in the initial connection message to query from /proc the name of the process we are connected to, and display that to the user. We use the "cmdline" procfs entry for the query since that is available on both Linux and FreeBSD (assuming procfs is mounted on the BSD instance).

---
 usertools/dpdk-telemetry.py | 5 +++++
 1 file changed, 5 insertions(+)
usertools/dpdk-telemetry.py +5 -0
index 181859658f..82b91f346f 100755
@@ -45,6 +45,11 @@ def handle_socket(path):
         return
     json_reply = read_socket(sock, 1024)
     output_buf_len = json_reply["max_output_len"]
+    pid = json_reply["pid"]
+    if os.path.exists('/proc/' + str(pid) + '/cmdline'):
+        with open('/proc/' + str(pid) + '/cmdline') as f:
+            argv0 = f.read(1024).split('\0')[0]
+            print("Connected to application: '" + os.path.basename(argv0) + "'")
 
     # get list of commands for readline completion
     sock.send("/".encode())
Signature · 1 line
2.27.0
#1 lore raw
Quoted 16 lines · Bruce Richardson

When the dpdk-telemetry client connects to a DPDK instance, we can use the PID provided in the initial connection message to query from /proc the name of the process we are connected to, and display that to the user. We use the "cmdline" procfs entry for the query since that is available on both Linux and FreeBSD (assuming procfs is mounted on the BSD instance).

---
  usertools/dpdk-telemetry.py | 5 +++++
  1 file changed, 5 insertions(+)
usertools/dpdk-telemetry.py +0 -0
index 181859658f..82b91f346f 100755

usertools/dpdk-telemetry.py def handle_socket(path): · line 50

Quoted 6 lines
usertools/dpdk-telemetry.py +3 -0
@@ -45,6 +45,11 @@ def handle_socket(path):
          return
      json_reply = read_socket(sock, 1024)
      output_buf_len = json_reply["max_output_len"]
+    pid = json_reply["pid"]
+    if os.path.exists('/proc/' + str(pid) + '/cmdline'):
+        with open('/proc/' + str(pid) + '/cmdline') as f:

First of all, this is better done using os.path.join:

path = os.path.join('/proc', str(pid), 'cmdline')
if os.path.exists(path):
with open(path) as f:
...

More importantly this isn't terribly Pythonic as it's not over-using exceptions :) IMO a better way would be:

try:
with open(path) as f:
...
except IOError as e:

    # ignore if doesn't exist
    if e.errno != errno.ENOENT:
        raise

usertools/dpdk-telemetry.py def handle_socket(path): · line 52

Quoted 2 lines
usertools/dpdk-telemetry.py +2 -0
+            argv0 = f.read(1024).split('\0')[0]
+            print("Connected to application: '" + os.path.basename(argv0) + "'")

Also, formatting is better than concatenation, e.g. at least:

bname = os.path.basename(argv0) print("Connected to application: '{}'".format(bname))

Quoted 4 lines
usertools/dpdk-telemetry.py +0 -0
      # get list of commands for readline completion
      sock.send("/".encode())
 
Signature · 2 lines
Thanks,
Anatoly
#2 lore raw
Quoted 26 lines · Anatoly
Quoted 16 lines · Bruce Richardson

When the dpdk-telemetry client connects to a DPDK instance, we can use the PID provided in the initial connection message to query from /proc the name of the process we are connected to, and display that to the user. We use the "cmdline" procfs entry for the query since that is available on both Linux and FreeBSD (assuming procfs is mounted on the BSD instance).

---
  usertools/dpdk-telemetry.py | 5 +++++
  1 file changed, 5 insertions(+)
usertools/dpdk-telemetry.py +0 -0
index 181859658f..82b91f346f 100755

usertools/dpdk-telemetry.py def handle_socket(path): · line 50

Quoted 6 lines
usertools/dpdk-telemetry.py +3 -0
@@ -45,6 +45,11 @@ def handle_socket(path):
          return
      json_reply = read_socket(sock, 1024)
      output_buf_len = json_reply["max_output_len"]
+    pid = json_reply["pid"]
+    if os.path.exists('/proc/' + str(pid) + '/cmdline'):
+        with open('/proc/' + str(pid) + '/cmdline') as f:

First of all, this is better done using os.path.join:

Quoted 4 lines

path = os.path.join('/proc', str(pid), 'cmdline')
if os.path.exists(path):
with open(path) as f:
...

Ok, I forgot that os.path.join can take > 2 parameters.

Quoted 4 lines

More importantly this isn't terribly Pythonic as it's not over-using exceptions :) IMO a better way would be:

Quoted 8 lines

try:
with open(path) as f:
...
except IOError as e:

    # ignore if doesn't exist
    if e.errno != errno.ENOENT:
        raise

Yes, I was thinking that I just wanted any exceptions to be raised, but you right that I should just ignore the not-found one and skip the printout.

Quoted 8 lines

usertools/dpdk-telemetry.py def handle_socket(path): · line 52

Quoted 2 lines
usertools/dpdk-telemetry.py +2 -0
+            argv0 = f.read(1024).split('\0')[0]
+            print("Connected to application: '" + os.path.basename(argv0) + "'")

Also, formatting is better than concatenation, e.g. at least:

bname = os.path.basename(argv0) print("Connected to application: '{}'".format(bname))

And f-strings are best of all, but we need python 3.6 for those. :-) I consider use of format vs concat a matter of taste, but I'll update as you suggest.

Thanks for the review.

/Bruce

PS: Python 3.5 has had its final release late last year:
https://www.python.org/downloads/release/python-3510/
We should soon consider updating our minimum required version to Python 3.6, allowing us to use f-strings in our python code rather than concatenation or explicit format calls.

#3 lore raw
Quoted 47 lines · Bruce Richardson
Quoted 26 lines · Anatoly
Quoted 16 lines · Bruce Richardson

When the dpdk-telemetry client connects to a DPDK instance, we can use the PID provided in the initial connection message to query from /proc the name of the process we are connected to, and display that to the user. We use the "cmdline" procfs entry for the query since that is available on both Linux and FreeBSD (assuming procfs is mounted on the BSD instance).

---
   usertools/dpdk-telemetry.py | 5 +++++
   1 file changed, 5 insertions(+)
usertools/dpdk-telemetry.py +0 -0
index 181859658f..82b91f346f 100755

usertools/dpdk-telemetry.py def handle_socket(path): · line 50

Quoted 6 lines
usertools/dpdk-telemetry.py +3 -0
@@ -45,6 +45,11 @@ def handle_socket(path):
           return
       json_reply = read_socket(sock, 1024)
       output_buf_len = json_reply["max_output_len"]
+    pid = json_reply["pid"]
+    if os.path.exists('/proc/' + str(pid) + '/cmdline'):
+        with open('/proc/' + str(pid) + '/cmdline') as f:

First of all, this is better done using os.path.join:

Quoted 4 lines

path = os.path.join('/proc', str(pid), 'cmdline')
if os.path.exists(path):
with open(path) as f:
...

Ok, I forgot that os.path.join can take > 2 parameters.

Quoted 4 lines

More importantly this isn't terribly Pythonic as it's not over-using exceptions :) IMO a better way would be:

Quoted 8 lines

try:
with open(path) as f:
...
except IOError as e:

     # ignore if doesn't exist
     if e.errno != errno.ENOENT:
         raise
Quoted 2 lines

Yes, I was thinking that I just wanted any exceptions to be raised, but you right that I should just ignore the not-found one and skip the printout.

'raise' will raise the exception up the stack, so you'll still get your exceptions that way - you'll just skip the one that says the file doesn't exist. plus, it also has a benefit of avoiding TOCTOU race :)

Quoted 15 lines
Quoted 9 lines

usertools/dpdk-telemetry.py def handle_socket(path): · line 52

Quoted 3 lines
usertools/dpdk-telemetry.py +2 -0
+            argv0 = f.read(1024).split('\0')[0]
+            print("Connected to application: '" + os.path.basename(argv0) + "'")

Also, formatting is better than concatenation, e.g. at least:

bname = os.path.basename(argv0) print("Connected to application: '{}'".format(bname))

And f-strings are best of all, but we need python 3.6 for those. :-) I consider use of format vs concat a matter of taste, but I'll update as you suggest.

Thanks for the review.

Quoted 8 lines

/Bruce

PS: Python 3.5 has had its final release late last year:
https://www.python.org/downloads/release/python-3510/
We should soon consider updating our minimum required version to Python 3.6, allowing us to use f-strings in our python code rather than concatenation or explicit format calls.

I seem to have a lot of difficulty remembering syntax for f-strings :P

Signature · 2 lines
Thanks,
Anatoly
#4 lore raw

PATCH v2 1/1 usertools/dpdk-telemetry: print name of app when connected

In reply to Bruce Richardson

When the dpdk-telemetry client connects to a DPDK instance, we can use the PID provided in the initial connection message to query from /proc the name of the process we are connected to, and display that to the user. We use the "cmdline" procfs entry for the query since that is available on both Linux and FreeBSD (assuming procfs is mounted on the BSD instance).

---
V2:
Updated with stylistic feedback from Anatoly, and split name query into a separate function.

---
 usertools/dpdk-telemetry.py | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
usertools/dpdk-telemetry.py +18 -0
index 181859658..b2acd92ba 100755
@@ -11,6 +11,7 @@
 import os
 import glob
 import json
+import errno
 import readline
 
 # global vars
@@ -32,6 +33,20 @@ def read_socket(sock, buf_len, echo=True):
     return ret
 
 
+def get_app_name(pid):
+    """ return the app name for a given pid, for printing """
+    proc_cmdline = os.path.join('/proc', str(pid), 'cmdline')
+    try:
+        with open(proc_cmdline) as f:
+            argv0 = f.read(1024).split('\0')[0]
+            return os.path.basename(argv0)
+    except IOError as e:
+        # ignore file not found errors
+        if e.errno != errno.ENOENT:
+            raise
+    return None
+
+
 def handle_socket(path):
     """ Connect to socket and handle user input """
     sock = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
@@ -45,6 +60,9 @@ def handle_socket(path):
         return
     json_reply = read_socket(sock, 1024)
     output_buf_len = json_reply["max_output_len"]
+    app_name = get_app_name(json_reply["pid"])
+    if app_name:
+        print('Connected to application: "%s"' % app_name)
 
     # get list of commands for readline completion
     sock.send("/".encode())

--
2.27.0

Acked-by on v2 1/1
#5 lore raw
Quoted 60 lines · Bruce Richardson

When the dpdk-telemetry client connects to a DPDK instance, we can use the PID provided in the initial connection message to query from /proc the name of the process we are connected to, and display that to the user. We use the "cmdline" procfs entry for the query since that is available on both Linux and FreeBSD (assuming procfs is mounted on the BSD instance).

---
V2:
Updated with stylistic feedback from Anatoly, and split name query into a separate function.

---
  usertools/dpdk-telemetry.py | 18 ++++++++++++++++++
  1 file changed, 18 insertions(+)
usertools/dpdk-telemetry.py +18 -1
index 181859658..b2acd92ba 100755
@@ -11,6 +11,7 @@
  import os
  import glob
  import json
+import errno
  import readline
 
  # global vars
@@ -32,6 +33,20 @@ def read_socket(sock, buf_len, echo=True):
      return ret
 
 
+def get_app_name(pid):
+    """ return the app name for a given pid, for printing """
+    proc_cmdline = os.path.join('/proc', str(pid), 'cmdline')
+    try:
+        with open(proc_cmdline) as f:
+            argv0 = f.read(1024).split('\0')[0]
+            return os.path.basename(argv0)
+    except IOError as e:
+        # ignore file not found errors
+        if e.errno != errno.ENOENT:
+            raise
+    return None
+
+
  def handle_socket(path):
      """ Connect to socket and handle user input """
      sock = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
@@ -45,6 +60,9 @@ def handle_socket(path):
          return
      json_reply = read_socket(sock, 1024)
      output_buf_len = json_reply["max_output_len"]
+    app_name = get_app_name(json_reply["pid"])
+    if app_name:
+        print('Connected to application: "%s"' % app_name)
 
      # get list of commands for readline completion
      sock.send("/".encode())
--
Quoted 2 lines

2.27.0

Signature · 2 lines
Thanks,
Anatoly
Acked-by on v2 1/1
#6 lore raw
In reply to Bruce Richardson
Quoted 8 lines · Bruce Richardson

When the dpdk-telemetry client connects to a DPDK instance, we can use the PID provided in the initial connection message to query from /proc the name of the process we are connected to, and display that to the user. We use the "cmdline" procfs entry for the query since that is available on both Linux and FreeBSD (assuming procfs is mounted on the BSD instance).

#7 lore raw

17/02/2021 14:57, Kevin Laatz:

Quoted 10 lines · Bruce Richardson
Quoted 7 lines

When the dpdk-telemetry client connects to a DPDK instance, we can use the PID provided in the initial connection message to query from /proc the name of the process we are connected to, and display that to the user. We use the "cmdline" procfs entry for the query since that is available on both Linux and FreeBSD (assuming procfs is mounted on the BSD instance).

Applied, thanks