From 896b3694ca062d747cd67e9e9ba246adb3fc706b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= Date: Mon, 5 Aug 2019 13:55:37 +0200 Subject: [PATCH 2/2] Repeat pututxline() if it fails with EINTR This is a partial fix for rhbz#1688848. We cannot resolve it completely until glibc bug rhbz#1734791 is fixed. See https://bugzilla.redhat.com/show_bug.cgi?id=1688848#c13. The maximum number of attempts is currently 2, which might seem low. However setting it to 2 was a decision based on data - see https://bugzilla.redhat.com/show_bug.cgi?id=1688848#c16. Resolves: rhbz#1688848 --- sysdeputil.c | 53 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/sysdeputil.c b/sysdeputil.c index bd1e8c9..4fbcca7 100644 --- a/sysdeputil.c +++ b/sysdeputil.c @@ -1203,6 +1203,8 @@ void vsf_insert_uwtmp(const struct mystr* p_user_str, const struct mystr* p_host_str) { + int attempts; + if (sizeof(s_utent.ut_line) < 16) { return; @@ -1231,16 +1233,35 @@ vsf_insert_uwtmp(const struct mystr* p_user_str, vsf_sysutil_strcpy(s_utent.ut_host, str_getbuf(p_host_str), sizeof(s_utent.ut_host)); s_utent.ut_tv.tv_sec = vsf_sysutil_get_time_sec(); - setutxent(); - (void) pututxline(&s_utent); - endutxent(); - s_uwtmp_inserted = 1; + for (attempts = 2; attempts > 0; --attempts) + { + struct utmpx* p_res; + setutxent(); + p_res = pututxline(&s_utent); + /* For now we'll ignore errors other than EINTR and EAGAIN */ + if (p_res != NULL || (errno != EINTR && errno != EAGAIN)) + { + break; + } + } + if (attempts == 0) + { + /* This makes us skip pututxline() in vsf_remove_uwtmp() */ + s_uwtmp_inserted = -1; + } + else + { + s_uwtmp_inserted = 1; + endutxent(); + } updwtmpx(WTMPX_FILE, &s_utent); } void vsf_remove_uwtmp(void) { + int attempts; + if (!s_uwtmp_inserted) { return; @@ -1249,9 +1270,27 @@ vsf_remove_uwtmp(void) vsf_sysutil_memclr(s_utent.ut_user, sizeof(s_utent.ut_user)); vsf_sysutil_memclr(s_utent.ut_host, sizeof(s_utent.ut_host)); s_utent.ut_tv.tv_sec = 0; - setutxent(); - (void) pututxline(&s_utent); - endutxent(); + if (s_uwtmp_inserted == 1) + { + for (attempts = 2; attempts > 0; --attempts) + { + struct utmpx* p_res; + setutxent(); + p_res = pututxline(&s_utent); + /* For now we'll ignore errors other than EINTR and EAGAIN */ + if (p_res != NULL || (errno != EINTR && errno != EAGAIN)) + { + break; + } + } + if (attempts != 0) + { + endutxent(); + } + } + /* Set s_uwtmp_inserted to 0 regardless of the result of + * pututxline() to make sure we won't run this function twice. + */ s_uwtmp_inserted = 0; s_utent.ut_tv.tv_sec = vsf_sysutil_get_time_sec(); updwtmpx(WTMPX_FILE, &s_utent); -- 2.20.1