Демон Linux, кажется, зависает на "recvfrom", обнаружил, что процесс procfs net поврежден и недоступен - PullRequest
0 голосов
/ 06 декабря 2018

У меня есть давно работающий демон linux, который создал «неблокирующую» привязку сокета на порту 65445, ожидающую UDP-пакет.Это может работать большую часть времени.

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

На этом этапе процесс не принимает никакого сигнала, поэтому я не могу его убить, сбросьте стек ядра:

Kernel Status:
[<ffffffff80385ff3>] number.isra.2+0x2d3/0x300
[<ffffffff802e0228>] address_space_init_once+0x88/0x120
[<ffffffff802e0200>] address_space_init_once+0x60/0x120
[<ffffffff802df880>] inode_wait+0x0/0x10
[<ffffffff802df889>] inode_wait+0x9/0x10
[<ffffffff802df880>] inode_wait+0x0/0x10
[<ffffffff80275dc0>] wake_bit_function+0x0/0x30
[<ffffffff802e0abd>] iget_locked+0x11d/0x180
[<ffffffff8030e1f0>] proc_get_inode+0x10/0xf0
[<ffffffff80313555>] proc_lookup_de+0x75/0xf0
[<ffffffff802d31bc>] d_alloc_and_lookup+0x3c/0x90
[<ffffffff802deeee>] d_lookup+0x2e/0x60
[<ffffffff802d3ea6>] do_lookup+0x296/0x3a0
[<ffffffff802ddcee>] dput+0x1e/0x190
[<ffffffff802d49eb>] link_path_walk+0x12b/0x850
[<ffffffff802dddb2>] dput+0xe2/0x190
[<ffffffff802d7437>] path_openat+0xb7/0x370
[<ffffffff802b4cfe>] tlb_finish_mmu+0xe/0x50
[<ffffffff802d7824>] do_filp_open+0x44/0xb0
[<ffffffff802e2905>] alloc_fd+0x45/0x130
[<ffffffff802c8a5c>] do_sys_open+0xec/0x1d0
[<ffffffff805a8afb>] system_call_fastpath+0x16/0x1b
[<ffffffffffffffff>] 0xffffffffffffffff

Это указывает на что-то не так в procfs, после дальнейшего исследования я обнаружил, что сетевой каталог procfs этого процесса был искажен, я даже не могу сделать ls /proc/*pid*/net, bash также зависает там.

Я сужаювниз из-за того, что процесс может зависнуть в 'recvfrom', который я просто не могу понять, поскольку это неблокированный сокет, часть моего кода выглядит следующим образом:

fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (fd < 0) {
    return ret;
}

if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, DEV, sizeof(DEV))
    < 0) {
    goto Exit;
}

rt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&sock_buf, sizeof(sock_buf));
if (rt < 0) {
    goto Exit;
}

rt = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&sock_buf, sizeof(sock_buf));
if (rt < 0) {
    goto Exit;
}

val = fcntl(fd, F_GETFL, 0);
if (val < 0) 
    return -1;
if (val & O_NONBLOCK)
    return 0;
val |= O_NONBLOCK;
fcntl(fd, F_SETFL, val);

memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET, addr.sin_port = PORT;
addr.sin_addr.s_addr = INADDR_ANY;

if (bind(fd, (void *)&addr, sizeof(addr)) < 0) {
    goto Exit;
}

Я добавляю этот сокет в epoll

struct epoll_event e;
e.events = EPOLLIN;
e.data.ptr = comm_handle;
rc = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &e);

получение пакета при возникновении события:

socklen_t from_len = sizeof(struct sockaddr_in);
memset(recv_buf, 0, 65000);
len = recvfrom(e->fd, recv_buf, 65000, 0, (struct sockaddr *)&from, &from_len);
if (len <= 0) {
    return -1;
}
...