You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
5.1 KiB
168 lines
5.1 KiB
From 534fd1f0c84b12ba6080a46e07c57ef913c77cba Mon Sep 17 00:00:00 2001
|
|
From: Radovan Sroka <rsroka@redhat.com>
|
|
Date: Thu, 25 Aug 2022 15:38:01 +0200
|
|
Subject: [PATCH] fapolicyd: Make write() nonblocking
|
|
|
|
- switch to read only and non blocking mode for pipe
|
|
- add 1 minute loop to wait for pipe to reappear
|
|
|
|
Sometimes during the system update/upgrade fapolicyd
|
|
get restarted e.g. when systemd gets updated.
|
|
That can lead to the situation where fapolicyd pipe
|
|
has been removed and created again.
|
|
In such cases rpm-plugin-fapolicyd gets stuck on
|
|
write() to the pipe which does not exist anymore.
|
|
After switching to non blocking file descriptor
|
|
we can try to reopen the pipe if there is an error
|
|
from write(). Assuming that a new pipe should appear
|
|
when fapolicyd daemon starts again.
|
|
If not then after 1 minute of waiting we expect
|
|
fapolicyd daemon to be not active and we let the
|
|
transaction continue.
|
|
|
|
Signed-off-by: Radovan Sroka <rsroka@redhat.com>
|
|
---
|
|
plugins/fapolicyd.c | 74 +++++++++++++++++++++++++++++++++++++++------
|
|
1 file changed, 65 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/plugins/fapolicyd.c b/plugins/fapolicyd.c
|
|
index 1ff50c30f..6c6322941 100644
|
|
--- a/plugins/fapolicyd.c
|
|
+++ b/plugins/fapolicyd.c
|
|
@@ -27,7 +27,7 @@ static rpmRC open_fifo(struct fapolicyd_data* state)
|
|
int fd = -1;
|
|
struct stat s;
|
|
|
|
- fd = open(state->fifo_path, O_RDWR);
|
|
+ fd = open(state->fifo_path, O_WRONLY|O_NONBLOCK);
|
|
if (fd == -1) {
|
|
rpmlog(RPMLOG_DEBUG, "Open: %s -> %s\n", state->fifo_path, strerror(errno));
|
|
goto bad;
|
|
@@ -55,15 +55,26 @@ static rpmRC open_fifo(struct fapolicyd_data* state)
|
|
}
|
|
|
|
state->fd = fd;
|
|
+
|
|
/* considering success */
|
|
return RPMRC_OK;
|
|
|
|
bad:
|
|
if (fd >= 0)
|
|
close(fd);
|
|
+
|
|
+ state->fd = -1;
|
|
return RPMRC_FAIL;
|
|
}
|
|
|
|
+static void close_fifo(struct fapolicyd_data* state)
|
|
+{
|
|
+ if (state->fd > 0)
|
|
+ (void) close(state->fd);
|
|
+
|
|
+ state->fd = -1;
|
|
+}
|
|
+
|
|
static rpmRC write_fifo(struct fapolicyd_data* state, const char * str)
|
|
{
|
|
ssize_t len = strlen(str);
|
|
@@ -86,6 +97,54 @@ static rpmRC write_fifo(struct fapolicyd_data* state, const char * str)
|
|
return RPMRC_FAIL;
|
|
}
|
|
|
|
+static void try_to_write_to_fifo(struct fapolicyd_data* state, const char * str)
|
|
+{
|
|
+ int reload = 0;
|
|
+ int printed = 0;
|
|
+
|
|
+ /* 1min/60s */
|
|
+ const int timeout = 60;
|
|
+
|
|
+ /* wait up to X seconds */
|
|
+ for (int i = 0; i < timeout; i++) {
|
|
+
|
|
+ if (reload) {
|
|
+ if (!printed) {
|
|
+ rpmlog(RPMLOG_WARNING, "rpm-plugin-fapolicyd: waiting for the service connection to resume, it can take up to %d seconds\n", timeout);
|
|
+ printed = 1;
|
|
+ }
|
|
+
|
|
+ (void) close_fifo(state);
|
|
+ (void) open_fifo(state);
|
|
+ }
|
|
+
|
|
+ if (state->fd >= 0) {
|
|
+ if (write_fifo(state, str) == RPMRC_OK) {
|
|
+
|
|
+ /* write was successful after few reopens */
|
|
+ if (reload)
|
|
+ rpmlog(RPMLOG_WARNING, "rpm-plugin-fapolicyd: the service connection has resumed\n");
|
|
+
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* failed write or reopen */
|
|
+ reload = 1;
|
|
+ sleep(1);
|
|
+
|
|
+ /* the last iteration */
|
|
+ /* consider failure */
|
|
+ if (i == timeout-1) {
|
|
+ rpmlog(RPMLOG_WARNING, "rpm-plugin-fapolicyd: the service connection has not resumed\n");
|
|
+ rpmlog(RPMLOG_WARNING, "rpm-plugin-fapolicyd: continuing without the service\n");
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
+}
|
|
+
|
|
+
|
|
static rpmRC fapolicyd_init(rpmPlugin plugin, rpmts ts)
|
|
{
|
|
if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))
|
|
@@ -102,10 +161,7 @@ static rpmRC fapolicyd_init(rpmPlugin plugin, rpmts ts)
|
|
|
|
static void fapolicyd_cleanup(rpmPlugin plugin)
|
|
{
|
|
- if (fapolicyd_state.fd > 0)
|
|
- (void) close(fapolicyd_state.fd);
|
|
-
|
|
- fapolicyd_state.fd = -1;
|
|
+ (void) close_fifo(&fapolicyd_state);
|
|
}
|
|
|
|
static rpmRC fapolicyd_tsm_post(rpmPlugin plugin, rpmts ts, int res)
|
|
@@ -116,9 +172,9 @@ static rpmRC fapolicyd_tsm_post(rpmPlugin plugin, rpmts ts, int res)
|
|
/* we are ready */
|
|
if (fapolicyd_state.fd > 0) {
|
|
/* send a signal that transaction is over */
|
|
- (void) write_fifo(&fapolicyd_state, "1\n");
|
|
+ (void) try_to_write_to_fifo(&fapolicyd_state, "1\n");
|
|
/* flush cache */
|
|
- (void) write_fifo(&fapolicyd_state, "2\n");
|
|
+ (void) try_to_write_to_fifo(&fapolicyd_state, "2\n");
|
|
}
|
|
|
|
end:
|
|
@@ -133,7 +189,7 @@ static rpmRC fapolicyd_scriptlet_pre(rpmPlugin plugin, const char *s_name,
|
|
|
|
if (fapolicyd_state.changed_files > 0) {
|
|
/* send signal to flush cache */
|
|
- (void) write_fifo(&fapolicyd_state, "2\n");
|
|
+ (void) try_to_write_to_fifo(&fapolicyd_state, "2\n");
|
|
|
|
/* optimize flushing */
|
|
/* flush only when there was an actual change */
|
|
@@ -176,7 +232,7 @@ static rpmRC fapolicyd_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
|
|
char * sha = rpmfiFDigestHex(fi, NULL);
|
|
|
|
snprintf(buffer, 4096, "%s %lu %64s\n", dest, size, sha);
|
|
- (void) write_fifo(&fapolicyd_state, buffer);
|
|
+ (void) try_to_write_to_fifo(&fapolicyd_state, buffer);
|
|
|
|
free(sha);
|
|
|
|
--
|
|
2.37.3
|
|
|