Skip to content

Commit

Permalink
klippy: set posix thread names (pthread_setname_np)
Browse files Browse the repository at this point in the history
  • Loading branch information
Piezoid committed Jul 3, 2023
1 parent a96608a commit b154415
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 2 deletions.
4 changes: 4 additions & 0 deletions klippy/chelper/serialqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// clock times, prioritizes commands, and handles retransmissions. A
// background thread is launched to do this work and minimize latency.

#define _GNU_SOURCE
#include <linux/can.h> // // struct can_frame
#include <math.h> // fabs
#include <pthread.h> // pthread_mutex_lock
Expand Down Expand Up @@ -674,6 +675,9 @@ serialqueue_alloc(int serial_fd, char serial_fd_type, int client_id)
if (ret)
goto fail;
ret = pthread_create(&sq->tid, NULL, background_thread, sq);
if (ret)
goto fail;
ret = pthread_setname_np(sq->tid, "klippy_cserial");
if (ret)
goto fail;

Expand Down
3 changes: 3 additions & 0 deletions klippy/klippy.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,4 +404,7 @@ def main():
sys.exit(-1)

if __name__ == '__main__':
import namedthreads
namedthreads.patch()
namedthreads.set_thread_name("klippy_main")
main()
73 changes: 73 additions & 0 deletions klippy/namedthreads.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import ctypes
import ctypes.util
import threading
import logging

# this is mostly copied from https://github.com/beniwohli/namedthreads/blob/master/namedthreads.py
# itself copied from https://bugs.python.org/issue15500#msg230736


def make_pthread_setname_np():
libpthread_path = ctypes.util.find_library("pthread")

if not libpthread_path:
# pthread library not found, not patching"
return

libpthread = ctypes.CDLL(libpthread_path)

if not hasattr(libpthread, "pthread_setname_np"):
# pthread library does not have pthread_setname_np function, not patching
return

pthread_setname_np = libpthread.pthread_setname_np
pthread_setname_np.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
pthread_setname_np.restype = ctypes.c_int
return pthread_setname_np

pthread_setname_np = make_pthread_setname_np()

def set_thread_name(name, thread=None):
if hasattr(name, "encode"):
name = name.encode('ascii', 'replace')
if thread is None:
thread = threading.current_thread()
ident = getattr(thread, "ident", None)
ret = -1
if ident is not None:
ret = pthread_setname_np(ident, name[:15])
if ret != 0:
raise RuntimeError(f'Failed to set thread name {thread=} {ident=} {name=}')

def patch():
if getattr(threading.Thread.start, "_namedthreads_patched", None):
# threading module is already patched
return

if pthread_setname_np is None:
logging.warn("Failed to get pthread_setname_np() wrapper")
return

orig_start = threading.Thread.start

def start(self):
orig_start(self)
try:
name = self.name
if name:
set_thread_name(name, self)
except Exception as e:
logging.warn("Failed to set thread name for %r: %s", self, e)

start._namedthreads_patched = True
start._namedthreads_orig = threading.Thread.start
threading.Thread.start = start
return True


def unpatch():
if not getattr(threading.Thread.start, "_namedthreads_patched", None):
# threading module is not patched
return
patched_start = threading.Threading.start
threading.Thread.start = patched_start._namedthreads_orig
2 changes: 1 addition & 1 deletion klippy/queuelogger.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def __init__(self, filename):
logging.handlers.TimedRotatingFileHandler.__init__(
self, filename, when='midnight', backupCount=5)
self.bg_queue = queue.Queue()
self.bg_thread = threading.Thread(target=self._bg_thread)
self.bg_thread = threading.Thread(target=self._bg_thread, name='klippy_logger')
self.bg_thread.start()
self.rollover_info = {}
def _bg_thread(self):
Expand Down
2 changes: 1 addition & 1 deletion klippy/serialhdl.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def _start_session(self, serial_dev, serial_fd_type=b'u', client_id=0):
self.ffi_lib.serialqueue_alloc(serial_dev.fileno(),
serial_fd_type, client_id),
self.ffi_lib.serialqueue_free)
self.background_thread = threading.Thread(target=self._bg_thread)
self.background_thread = threading.Thread(target=self._bg_thread, name='klippy_serial')
self.background_thread.start()
# Obtain and load the data dictionary from the firmware
completion = self.reactor.register_callback(self._get_identify_data)
Expand Down

0 comments on commit b154415

Please sign in to comment.