2017年12月14日 星期四

Process/Thread name in Android native layer

看起來在 libc/bionic 裡面有個 pthread_setname_np.cpp 可以去設置 process name,
但是不曉得為什麼沒有提供 getname 方法 (security?)

setname 的使用方法如下:

pthread_setname_np(pthread_self(), "xxx");

他的實作如下:

int pthread_setname_np(pthread_t t, const char* thread_name) {
  ErrnoRestorer errno_restorer;

  size_t thread_name_len = strlen(thread_name);
  if (thread_name_len >= MAX_TASK_COMM_LEN) {
    return ERANGE;
  }

  // Changing our own name is an easy special case.
  if (t == pthread_self()) {
    return prctl(PR_SET_NAME, thread_name) ? errno : 0;
  }

  // We have to change another thread's name.
  pthread_internal_t* thread = __pthread_internal_find(t);
  if (thread == NULL) {
    return ENOENT;
  }
  pid_t tid = thread->tid;

  char comm_name[sizeof(TASK_COMM_FMT) + 8];
  snprintf(comm_name, sizeof(comm_name), TASK_COMM_FMT, tid);
  int fd = open(comm_name, O_CLOEXEC | O_WRONLY);
  if (fd == -1) {
    return errno;
  }
  ssize_t n = TEMP_FAILURE_RETRY(write(fd, thread_name, thread_name_len));
  close(fd);

  if (n < 0) {
    return errno;
  } else if (n != static_cast<ssize_t>(thread_name_len)) {
    return EIO;
  }
  return 0;
}

我們可以如果是在當前的 thread name 進行更名的話,
就會直接透過 prctl(PR_SET_NAME, thread_name) 來完成

否則則會嘗試去開啟 /proc/self/task/%d/comm , 其中 %d 將會帶入目標 thread 的 tid,
並直接對他做 write 的動作.

這個 PR_SET_NAME 定義在 bionic/libc/kernel/uapi/linux/prctl.h
#define PR_SET_NAME 15
#define PR_GET_NAME 16
但沒有看到去呼叫 PR_GET_NAME 的方法

我們可以在 bionic/linker/debugger.cpp 找到一個較為接近的例子:

  char thread_name[MAX_TASK_NAME_LEN + 1]; // one more for termination
  if (prctl(PR_GET_NAME, reinterpret_cast<unsigned long>(thread_name), 0, 0, 0) != 0) {
    strcpy(thread_name, "<name unknown>");
  } else {
    // short names are null terminated by prctl, but the man page
    // implies that 16 byte names are not.
    thread_name[MAX_TASK_NAME_LEN] = 0;
  }

不過較奇妙的是他並沒有去 /proc/self/task 下面尋找對應的 tid
看起來是只要去 $cat /proc/<tid>/comm 就可以拿到 process name 了
(並且 /proc/<tid>/comm 這一路上的權限看起來都是有開啟的...)


沒有留言:

張貼留言

不定參數印 log

From the UNIXProcess_md.c #ifdef DEBUG_PROCESS   /* Debugging process code is difficult; where to write debug output? */ static void deb...