From 85a77eea8d7114675602a33d2e067fd7c4ad0624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 12 Jan 2014 11:38:56 -0500 Subject: [PATCH] core: do not segfault if swap activity happens when /proc/swaps is not open In https://bugzilla.redhat.com/show_bug.cgi?id=969795 systemd crashes in swap_dispatch_reload called from manager_loop becuase m->proc_swaps is NULL. It can legitimately be NULL if something went wrong when initially enumerating swap devices when starting the manager. This is probably a sign of significant trouble, but let's do our best to recover. --- src/core/swap.c | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/src/core/swap.c b/src/core/swap.c index 147f710..f295b65 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -1068,14 +1068,40 @@ static int swap_load_proc_swaps(Manager *m, bool set_flags) { return r; } +static int open_proc_swaps(Manager *m) { + if (!m->proc_swaps) { + struct epoll_event ev = { + .events = EPOLLPRI, + .data.ptr = &m->swap_watch, + }; + + m->proc_swaps = fopen("/proc/swaps", "re"); + if (!m->proc_swaps) + return (errno == ENOENT) ? 0 : -errno; + + m->swap_watch.type = WATCH_SWAP; + m->swap_watch.fd = fileno(m->proc_swaps); + + if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->swap_watch.fd, &ev) < 0) + return -errno; + } + + return 0; +} + int swap_dispatch_reload(Manager *m) { /* This function should go as soon as the kernel properly notifies us */ + int r; if (_likely_(!m->request_reload)) return 0; m->request_reload = false; + r = open_proc_swaps(m); + if (r < 0) + return r; + return swap_fd_event(m, EPOLLPRI); } @@ -1225,22 +1251,9 @@ static int swap_enumerate(Manager *m) { int r; assert(m); - if (!m->proc_swaps) { - struct epoll_event ev = { - .events = EPOLLPRI, - .data.ptr = &m->swap_watch, - }; - - m->proc_swaps = fopen("/proc/swaps", "re"); - if (!m->proc_swaps) - return (errno == ENOENT) ? 0 : -errno; - - m->swap_watch.type = WATCH_SWAP; - m->swap_watch.fd = fileno(m->proc_swaps); - - if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->swap_watch.fd, &ev) < 0) - return -errno; - } + r = open_proc_swaps(m); + if (r < 0) + return r; r = swap_load_proc_swaps(m, false); if (r < 0)