GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Python should support exporting thread names to the OS · Issue #59705 · python/cpython

Python should support exporting thread names to the OS #59705

New issue
Copy link
New issue
Copy link
Closed
Closed
Python should support exporting thread names to the OS#59705
Copy link
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancementA feature request or enhancement

Description

bra
mannequin
opened on Jul 30, 2012
Issue body actions
BPO 15500
Nosy @jcea, @pitrou, @vstinner, @tiran, @bitdancer, @asvetlov, @florentx, @socketpair, @eryksun, @ZackerySpytz, @arhadthedev
PRs
  • gh-59705: Export threading.Thread() names to the OS #14578
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2012-07-30.12:19:30.305>
    labels = ['type-feature', 'library', '3.10', '3.11']
    title = 'Python should support exporting thread names to the OS'
    updated_at = <Date 2022-01-18.21:32:45.293>
    user = 'https://bugs.python.org/bra'

    bugs.python.org fields:

    activity = <Date 2022-01-18.21:32:45.293>
    actor = 'pitrou'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Library (Lib)']
    creation = <Date 2012-07-30.12:19:30.305>
    creator = 'bra'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 15500
    keywords = ['patch']
    message_count = 10.0
    messages = ['166890', '167166', '167459', '167552', '167560', '230736', '377332', '406336', '410896', '410898']
    nosy_count = 14.0
    nosy_names = ['jcea', 'pitrou', 'vstinner', 'christian.heimes', 'Arfrever', 'r.david.murray', 'asvetlov', 'flox', 'bra', 'kovid', 'socketpair', 'eryksun', 'ZackerySpytz', 'arhadthedev']
    pr_nums = ['14578']
    priority = 'normal'
    resolution = None
    stage = 'patch review'
    status = 'open'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue15500'
    versions = ['Python 3.10', 'Python 3.11']

    Linked PRs

    • gh-59705: Add _thread.set_name() function #127338
    • gh-59705: Set OS thread name when Thread.name is changed #127702
    • gh-59705: Implement _thread.set_name() on Windows #128675
    • gh-59705: Document OS thread name change #128800
    • gh-59705: Make PYTHREAD_NAME_MAXLEN macro private #128945
    • gh-59705: Fix solaris detection in test_set_name #132012

    Activity

    Next
    1. bra commented on Jul 30, 2012

      @bra
      bramannequin
      on Jul 30, 2012
      MannequinAuthor
      More actions

      Python class Thread has a "name" argument, which sets the name of the given thread. This name is used only internally, while there is a possibility to set this on an OS-level.
      Related discussion:
      http://stackoverflow.com/questions/2369738/can-i-set-the-name-of-a-thread-in-pthreads-linux

      #include <pthread.h>
      int pthread_setname_np(pthread_t thread, const char *name);
      
      // FreeBSD & OpenBSD: function name is slightly different
      void pthread_set_name_np(pthread_t tid, const char *name);
      
      // Mac OS X: it only seems applicable to the current thread (no thread ID)
      int pthread_setname_np(const char*);

      It would be very useful if Python set the name parameter with the above pthread calls, so the user/developer could see which threads do what in ps or top.

    2. bra
      added
      stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
      type-featureA feature request or enhancementA feature request or enhancement
      on Jul 30, 2012
    3. tiran commented on Aug 1, 2012

      @tiran
      tiran
      on Aug 1, 2012
      Member
      More actions

      +1

      win32 supports thread names, too. http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx

    4. pitrou commented on Aug 4, 2012

      @pitrou
      pitrou
      on Aug 4, 2012
      Member
      More actions

      I don't think this should be done by default as it will break people's expectations and, perhaps worse, compatibility.

    5. bra commented on Aug 6, 2012

      @bra
      bramannequin
      on Aug 6, 2012
      MannequinAuthor
      More actions

      "I don't think this should be done by default as it will break people's expectations and, perhaps worse, compatibility."
      I won't mind another thread naming API, if somebody does this. :)
      But personally I expected python to name my threads (and if the OS supports it, on that level), I was actually surprised to see that it doesn't, mostly because I remembered a patch for FreeBSD, which did this years ago, so I thought it has been merged into mainline since then.

    6. bitdancer commented on Aug 6, 2012

      @bitdancer
      bitdancer
      on Aug 6, 2012
      Member
      More actions

      It is indeed the compatibility that is the worse issue. The problem is what people have gotten used to and may have coded their applications to expect/deal with. I agree with you that most people would *not* find it surprising to see the name reflected in the OS, but I don't think the convenience of that is worth introducing a potential backward incompatibility.

      On the other hand, I think this might be an appropriate place to use a global control, so that getting thread names out to the OS would require adding just a single line of code to any given application. I know of an application that does this. It chose to implement it as a global change, and that makes sense to me.

    7. kovid commented on Nov 6, 2014

      @kovid
      kovidmannequin
      on Nov 6, 2014
      Mannequin
      More actions

      Just FYI, a pure python2 implementation that monkey patches Thread.start() to set the OS level thread name intelligently.

              import ctypes, ctypes.util, threading
              libpthread_path = ctypes.util.find_library("pthread")
              if libpthread_path:
                  libpthread = ctypes.CDLL(libpthread_path)
                  if hasattr(libpthread, "pthread_setname_np"):
                      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
                      orig_start = threading.Thread.start
                      def new_start(self):
                          orig_start(self)
                          try:
                              name = self.name
                              if not name or name.startswith('Thread-'):
                                  name = self.__class__.__name__
                                  if name == 'Thread':
                                      name = self.name
                              if name:
                                  if isinstance(name, unicode):
                                      name = name.encode('ascii', 'replace')
                                  ident = getattr(self, "ident", None)
                                  if ident is not None:
                                      pthread_setname_np(ident, name[:15])
                          except Exception:
                              pass  # Don't care about failure to set name
                      threading.Thread.start = new_start
    8. bitdancer
      changed the title [-]Python should support naming threads[/-] [+]Python should support exporting thread names to the OS[/+] on Nov 30, 2015
    9. ZackerySpytz
      added
      3.9 (EOL)end of lifeend of life
      on Jul 3, 2019
    10. vstinner commented on Sep 22, 2020

      @vstinner
      vstinner
      on Sep 22, 2020
      Member
      More actions

      bpo-18006 "Set thread name in linux kernel" was marked as a duplicate of this issue:

      """
      In linux (Since 2.6.9) we can use syscall

      prctl(PR_SET_NAME, "Some thread name")

      to set thread name to the kernel.
      (...)
      """

    11. vstinner
      added
      3.10 (EOL)end of lifeend of life
      and removed
      3.9 (EOL)end of lifeend of life
      on Sep 22, 2020
    12. eryksun commented on Nov 15, 2021

      @eryksun
      eryksun
      on Nov 15, 2021
      Contributor
      More actions

      Zackery, here's an initial draft implementation for Windows 10+ that's based on the interface you created in PR 14578. It calls WinAPI SetThreadDescription(), which sets the thread's name directly in the kernel thread object (i.e. ETHREAD.ThreadName). This function was added to the API in Windows 10 version 1607 (10.0.14393), so Windows 8.1 systems and older Windows 10 systems aren't supported. I'd rather not implement the exception-based approach for older Windows systems. It doesn't really name the thread and only works when a debugger is attached to the process.

      This initial draft blindly assumes that the filesystem encoding is UTF-8. That's been the case in Windows since Python 3.6, unless configured to use the legacy ANSI encoding, e.g. by setting PYTHONLEGACYWINDOWSFSENCODING. PyThread_set_thread_name() could be changed to use CP_ACP instead of CP_UTF8 when legacy mode is enabled.

      I set the truncation limit to 64 characters. It could be lowered to 15 to match what you implemented for POSIX, but I think that's too short. The limit could also effectively be removed by truncating to the system limit of 32766 characters. That would be simpler since the code wouldn't have to worry about surrogate pairs.

      Python/thread_nt.h:

          typedef HRESULT (WINAPI *PF_SET_THREAD_DESCRIPTION)(HANDLE, PCWSTR);
          static PF_SET_THREAD_DESCRIPTION pSetThreadDescription = NULL;
      
          static void
          PyThread__init_thread(void)
          {
              // Initialize pSetThreadDescription.
              // Minimum supported Windows version: 10.0.14393 (1607)
              int i = 0;
              LPCWSTR module_names[2] = {
                  L"api-ms-win-core-processthreads-l1-1-3", // i.e. kernel32
                  L"kernelbase",
              };
              // Most "ms-win-core" API sets (except for COM/WinRT) are implemented
              // by modules that are always loaded, including ntdll, kernelbase, and
              // kernel32, so it's safe to use GetModuleHandleW().
              do {
                  pSetThreadDescription = (PF_SET_THREAD_DESCRIPTION)GetProcAddress(
                      GetModuleHandleW(module_names[i]), "SetThreadDescription");
              } while (pSetThreadDescription == NULL &&
                       ++i < Py_ARRAY_LENGTH(module_names));
          }
      
          int
          PyThread_set_thread_name(const char *name)
          {
              HRESULT hr = 0;
              wchar_t *wname = NULL;
      
              if (!initialized) {
                  PyThread_init_thread();
              }
              if (name == NULL || *name == '\0') {
                  hr = E_INVALIDARG;
                  goto exit;
              }
              if (pSetThreadDescription == NULL) {
                  hr = E_NOTIMPL;
                  goto exit;
              }
      
              // cch includes the terminating null character.
              int cch = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0);
              if (cch > 0) {
                  wname = PyMem_RawMalloc(cch * sizeof(wchar_t));
                  if (wname == NULL) {
                      hr = E_OUTOFMEMORY;
                      goto exit;
                  }
                  cch = MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, cch);
              }
              if (cch == 0) {
                  hr = HRESULT_FROM_WIN32(GetLastError());
                  goto exit;
              }
      
              // Truncate the name to 64 characters, accounting for surrogate pairs.
              // The OS limit is 32766 wide characters, but long names aren't of
              // practical use.
              int i = 0;
              for (int len = 0; i < (cch - 1) && len < 64; i++, len++) {
                  if (i < (cch - 2) && IS_SURROGATE_PAIR(wname[i], wname[i + 1])) {
                      i++; // Skip the trailing surrogate.
                  }
              }
              wname[i] = L'\0';
      
              hr = pSetThreadDescription(GetCurrentThread(), wname);
      
          exit:
              if (wname != NULL) {
                  PyMem_RawFree(wname);
              }
              if (FAILED(hr)) {
                  return (int)hr;
              }
              return 0;
          }

      Modules/_threadmodule.c:

          static PyObject *
          _thread__set_thread_name_impl(PyObject *module, PyObject *name)
          {
              int error = PyThread_set_thread_name(PyBytes_AS_STRING(name));
          #ifdef MS_WINDOWS
              // For Python code, ignore a not-implemented error, which means
              // it's a Windows 8.1 system or older Windows 10 system.
              if (error == (int)E_NOTIMPL) {
                  error = 0;
              }
          #endif
              if (error) {
                  Py_DECREF(name);
                  PyErr_SetString(ThreadError, "setting the thread name failed");
                  return NULL;
              }
              Py_DECREF(name);
              Py_RETURN_NONE;
          }
    13. eryksun
      added
      3.11only security fixesonly security fixes
      on Nov 15, 2021
    14. 21 remaining items

    15. vstinner
      added 2 commits that reference this issue on Jan 9, 2025

      pythongh-59705: Implement _thread.set_name() on Windows

      b9f2363

      pythongh-59705: Implement _thread.set_name() on Windows

      479c7fb
    16. vstinner commented on Jan 9, 2025

      @vstinner
      vstinner
      on Jan 9, 2025
      Member
      More actions

      I wrote PR gh-128675 to implement set_name() and _get_name() on Windows with SetThreadDescription() and GetThreadDescription().

      Reacted by Xavier G. and Sam Morris
    17. vstinner
      added 5 commits that reference this issue on Jan 13, 2025

      pythongh-59705: Document OS thread name change

      a0a5edb

      gh-59705: Document OS thread name change (#128800)

      d786ac7

      gh-59705: Implement _thread.set_name() on Windows (#128675)

      d7f703d

      pythongh-59705: Make PYTHREAD_NAME_MAXLEN macro private

      de9d2fa

      gh-59705: Make PYTHREAD_NAME_MAXLEN macro private (#128945)

      81159fc
    18. srinivasreddy
      added 2 commits that reference this issue on Jan 21, 2025

      pythongh-59705: Implement _thread.set_name() on Windows (python#128675)

      5823ad8

      pythongh-59705: Make PYTHREAD_NAME_MAXLEN macro private (python#128945)

      bdf4c38
    19. vstinner commented on Jan 24, 2025

      @vstinner
      vstinner
      on Jan 24, 2025
      Member
      More actions

      The implementation is now complete, I close the issue. Thanks for helping me to implement this feature!

      Reacted by Xavier G., debauer and An Long
    20. vstinner
      closed this as completedon Jan 24, 2025
    21. github-project-automation
      moved this to Done in Threading issues 🧵on Jan 24, 2025
    22. kulikjak
      added a commit that references this issue on Apr 2, 2025

      pythongh-59705: Fix solaris detection in test_set_name

      6ade825
    23. vstinner
      added a commit that references this issue on Apr 2, 2025

      gh-59705: Fix solaris detection in test_threading.test_set_name() (#1…

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

    Metadata

    Metadata

    Assignees

    No one assigned

      Labels

      stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancementA feature request or enhancement

      Projects

      • Threading issues 🧵
        Status
        Done
        Show more project fields

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.