Как получить уведомление, когда другой конец пары сокетов закрыт?

После отключения сервера X11 и повторного входа в систему сокет UNIX X11 в /tmp/.X11-unix/X0был удален и воссоздан, а файл cookie сеанса X11 в ~/.Xauthorityбыл заменен новым случайным файлом cookie.

Даже если значение переменной окружения DISPLAYтакое же, приложения должны будут закрыться и повторно -открыть сокет и повторно -прочитать файл cookie. Насколько мне известно, не существует универсального механизма, который сигнализировал бы об этом каким-либо приложениям X11. И это будет только первый шаг :, после чего приложения должны будут полностью воссоздать все свои окна и другие объекты графического интерфейса с сервером X11 и восстановить их состояние, чтобы оно соответствовало внутреннему состоянию программы. Боюсь, этой функции не существует.

Лучшее, что вы можете сделать, это использовать kill -HUPдля остановки приложений, давая им возможность автоматически -сохранить всю несохраненную работу, если они были запрограммированы на это, а затем перезапустить их как обычно.

(Это на самом деле точно соответствует первоначальному значению сигнала HUP:изначально означало, что модемное соединение стационарной линии пользователя было разорвано, и приложение должно сохранять любую несохраненную работу таким образом, чтобы ее можно было восстановить. в новом сеансе, а затем выйти.)

1
21.04.2020, 04:50
1 ответ

Я составил пример приложения на основе вашего описания с небольшими отличиями. Во-первых, я использую SOCK_STREAMвместо SOCK_DGRAM. Это изменение дает мне поведение, которое вы ищете--POLLHUPозначает, что сокет больше не подключен; SOCK_DGRAMне является сокетом, ориентированным на соединение -. Есть ли причина, по которой вам нужно использовать SOCK_DGRAM?

Второе небольшое различие между этим примером и тем, что вы описываете, заключается в том, что я использую fork()вместо posix_spawn(). Это не должно влиять на поведение, которое вас интересует; просто мне было проще написать самостоятельный -пример с fork().

#include <poll.h>
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>

int main(void)
{
    int sockets[2] = {};

    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) {
        perror("socketpair");
        return 1;
    }

    const pid_t pid = fork();
    if (pid < 0) {
        perror("fork");
        return 2;
    }

    if (pid > 0) {
        /* parent */
        close(sockets[0]);
        sockets[0] = 0;

        for (int i = 0; i < 3; ++i) {
            write(sockets[1], "hello", sizeof("hello"));
            sleep(2);
        }

        /* sockets[1] will get closed on parent termination */
        return 0;
    }

    /* child */
    close(sockets[1]);
    sockets[1] = 0;

    struct pollfd fds = {
       .fd = sockets[0],
       .events = POLLIN | POLLHUP,
    };

    while (poll(&fds, 1, 10 * 1000) > 0) {
        if (fds.revents & POLLHUP) {
            printf("--- Received hangup\n");
            break;
        }
        if (fds.revents & POLLERR) {
            printf("!!! Received error\n");
            break;
        }
        if (fds.revents & POLLIN) {
            char buffer[32] = {};

            if (recv(sockets[0], buffer, sizeof buffer, 0) < 0) {
                perror("recv");
                return 3;
            }

            printf("--> Received message '%s'\n", buffer);
        }
    }

    /* sockets[0] will get closed on child termination */
    return 0;
}

В этой программе родитель пишет сообщения дочернему; дочерний элемент получает эти сообщения и обрабатывает их (здесь, просто выводит их на стандартный вывод ). Родитель отправляет 3 сообщения, затем завершает работу.

Когда я запускаю эту программу, я вижу поведение, которое, как я думаю, вы ищете:

$./a.out
--> Received message 'hello'
--> Received message 'hello'
--> Received message 'hello'
--- Received hangup

Если вы должны использовать SOCK_DGRAM, то вызов poll()в конечном итоге истечет по тайм-ауту (в моем примере у меня есть тайм-аут 10 -секунд ). Вы можете закрыть клиентский процесс в этом событии.

1
19.03.2021, 02:27

Теги

Похожие вопросы