1# Copyright 2017 The Abseil Authors.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""A tiny stand alone library to change the kernel process name on Linux."""
16
17import os
18import sys
19
20# This library must be kept small and stand alone.  It is used by small things
21# that require no extension modules.
22
23
24def make_process_name_useful():
25  """Sets the process name to something better than 'python' if possible."""
26  set_kernel_process_name(os.path.basename(sys.argv[0]))
27
28
29def set_kernel_process_name(name):
30  """Changes the Kernel's /proc/self/status process name on Linux.
31
32  The kernel name is NOT what will be shown by the ps or top command.
33  It is a 15 character string stored in the kernel's process table that
34  is included in the kernel log when a process is OOM killed.
35  The first 15 bytes of name are used.  Non-ASCII unicode is replaced with '?'.
36
37  Does nothing if /proc/self/comm cannot be written or prctl() fails.
38
39  Args:
40    name: bytes|unicode, the Linux kernel's command name to set.
41  """
42  if not isinstance(name, bytes):
43    name = name.encode('ascii', 'replace')
44  try:
45    # This is preferred to using ctypes to try and call prctl() when possible.
46    with open('/proc/self/comm', 'wb') as proc_comm:
47      proc_comm.write(name[:15])
48  except EnvironmentError:
49    try:
50      import ctypes  # pylint: disable=g-import-not-at-top
51    except ImportError:
52      return  # No ctypes.
53    try:
54      libc = ctypes.CDLL('libc.so.6')
55    except EnvironmentError:
56      return  # No libc.so.6.
57    pr_set_name = ctypes.c_ulong(15)  # linux/prctl.h PR_SET_NAME value.
58    zero = ctypes.c_ulong(0)
59    try:
60      libc.prctl(pr_set_name, name, zero, zero, zero)
61      # Ignore the prctl return value.  Nothing we can do if it errored.
62    except AttributeError:
63      return  # No prctl.
64