您是否应该释放传递给prctl()的内存?

时间:2019-07-01 14:53:44

标签: c linux

我正在使用prctl()来更改C语言中的pthreads线程名称:

  // Set our thread name to assist with debugging a running process
  char *threadName = calloc(16, sizeof(char));
  sprintf(threadName, "My Own Thread");
  prctl(PR_SET_NAME, threadName);

我的问题是在char *threadName通话之后是否应该立即释放prctl()

prcrl()是否可以安全地复制字符串参数,是否可以在需要时释放所提供的变量?

当我免费使用valgrind进行内存测试时,没有发现任何问题。我担心会导致难以跟踪的并发/内存问题。

编辑:我不认为建议的问题Can calloc ever safely be used without free?回答了有关系统/内核功能的具体问题,特别是prctl()要求调用者不要释放提供的内存

2 个答案:

答案 0 :(得分:2)

是的,通常,标准函数会在返回之前根据需要复制缓冲区,而将原始传递的缓冲区的所有权留给调用函数。

答案 1 :(得分:1)

我找不到任何文件明确表明释放传递给prctl( PR_SET_NAME, name )的字符串是安全的(很可能存在于某处)。

对手册页,glibc源代码和Linux内核源代码的检查表明,调用prctl()之后释放内存是安全的。

Linux prctl() man pagePR_SET_NAME指出了这一点:

  

PR_SET_NAME(自Linux 2.6.9起)

     

使用中的值设置调用线程的名称                 (char *) arg2指向的位置。名称最多                 16个字节长,包括终止的空字节。 (如果                 字符串的长度,包括终止的空字节,                 超过16个字节,该字符串将被静默截断。)这是                 可以通过pthread_setname_np(3)设置的相同属性                 并使用pthread_getname_np(3)进行检索。该属性是                 同样可以通过/proc/self/task/[tid]/comm访问,其中tid                 是调用线程的名称。

这里的关键是语句“同样可以通过/proc/self/task/[tid]/comm访问该属性”。这意味着必须将提供的字符串复制到内核空间中。措辞“在由( char * ) arg2指向的位置使用值”确实看起来令人困惑和不清楚,这有可能直接使用传递给prctl()的字符串。但是“要通过/proc/...进行访问,需要在内核空间中进行复制。

glibc source有点难以理解。在您的进程调用prctl()时,我无法确切地找到实际执行的代码,但是我发现的是直接将指针传递给内核的系统调用。

Linux kernel source is pretty clear。将字符串从用户空间复制到内核空间:

case PR_SET_NAME:
    comm[sizeof(me->comm) - 1] = 0;
    if (strncpy_from_user(comm, (char __user *)arg2,
                  sizeof(me->comm) - 1) < 0)
        return -EFAULT;
    set_task_comm(me, comm);
    proc_comm_connector(me);
    break;

确定的测试将是调用prctl()设置名称,然后修改传递给prctl()的字符串。如果线程名称未更改,则必须已创建副本。