Позволяет ли Linux переназначать идентификаторы групп процессов на процессы? - PullRequest
9 голосов
/ 22 июля 2011

Предположим, pid X является лидером группы процессов и X завершается, но другие процессы в группе процессов продолжают работать (с X в качестве pgid). Будет ли Linux препятствовать назначению значения X в качестве pid для нового процесса?

Я спрашиваю об этом из-за сбоя, в котором POSIX допускает setsid:

[EPERM] Вызывающий процесс уже является лидером группы процессов, или ID группы процессов, отличных от вызывающего процесса, совпадает с идентификатором процесса вызывающего процесса.

Эта ошибка, по-видимому, является неисправимым условием для кода, использующего группы процессов (т.е. оболочки), которые будут запускаться «случайным образом», что делает его еще более одиозным. Я предположил бы, что любая реализация, нацеленная на нормальные уровни качества, избежала бы переназначения X как pid, в то время как это все еще используется как pgid, но я нигде не могу найти это документированное.

Ответы [ 2 ]

6 голосов
/ 22 июля 2011

Не проблема, потому что fork гарантирует :

ИД дочернего процесса также не должен совпадать ни с одним идентификатором активной группы процессов.

И fork - единственный способ создания новых процессов.

5 голосов
/ 22 июля 2011

Немо верно, что POSIX гарантирует, что fork() не будет повторно использовать существующий PGID в качестве PID; Тем не менее, это еще не все.

Группы процессов и руководители групп процессов также можно изменить с помощью setpgid(). Следующий пример кода вызывает существование группы процессов, равной PID текущего процесса, в котором текущий процесс отсутствует:

#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>

int main()
{
    pid_t pgrp_orig;
    pid_t child;
    int status;

    /* Fork so that we are not a process group leader */
    if (fork()) {
        /* Grandparent process */
        wait(&status);
        return 0;
    }

    /* Record our original process group, then start a new one */
    pgrp_orig = getpgrp();
    if (setpgid(0, 0))
        perror("setpgid");

    child = fork();

    if (!child) {
        /* Child process */
        pause();
        return 0;
    }

    /* Switch back to original process group.  Child remains in the new one */
    if (setpgid(0, pgrp_orig))
        perror("setpgid");

    printf("Parent pid=%ld, pgid=%ld\n", (long)getpid(), (long)getpgrp());
    printf("Child pid=%ld, pgid=%ld\n", (long)child, (long)getpgid(child));

    /* Wake child up to finish up */
    kill(child, SIGUSR1);
    wait(&status);

    return 0;
}

Обратите внимание, что если родительский процесс попытается вызвать setsid() здесь до выхода из дочернего процесса, будет вызвано условие сбоя, о котором вы спрашивали.

Однако из-за ограничений допустимых переходов, которые может вызвать setpgid(), это не может вызвать случайные сбои, о которых вы беспокоитесь. Поломка ограничивается одним сеансом.

...