После отключения сервера X11 и повторного входа в систему сокет UNIX X11 в /tmp/.X11-unix/X0
был удален и воссоздан, а файл cookie сеанса X11 в ~/.Xauthority
был заменен новым случайным файлом cookie.
Даже если значение переменной окружения DISPLAY
такое же, приложения должны будут закрыться и повторно -открыть сокет и повторно -прочитать файл cookie. Насколько мне известно, не существует универсального механизма, который сигнализировал бы об этом каким-либо приложениям X11. И это будет только первый шаг :, после чего приложения должны будут полностью воссоздать все свои окна и другие объекты графического интерфейса с сервером X11 и восстановить их состояние, чтобы оно соответствовало внутреннему состоянию программы. Боюсь, этой функции не существует.
Лучшее, что вы можете сделать, это использовать kill -HUP
для остановки приложений, давая им возможность автоматически -сохранить всю несохраненную работу, если они были запрограммированы на это, а затем перезапустить их как обычно.
(Это на самом деле точно соответствует первоначальному значению сигнала HUP
:изначально означало, что модемное соединение стационарной линии пользователя было разорвано, и приложение должно сохранять любую несохраненную работу таким образом, чтобы ее можно было восстановить. в новом сеансе, а затем выйти.)
Я составил пример приложения на основе вашего описания с небольшими отличиями. Во-первых, я использую 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 -секунд ). Вы можете закрыть клиентский процесс в этом событии.