This is an automated email from the git hooks/post-receive script. guillem pushed a commit to branch main in repository dpkg.
View the commit online: https://git.dpkg.org/cgit/dpkg/dpkg.git/commit/?id=4d4e2e1186acae606de0b1f82ca888b6772ea89e commit 4d4e2e1186acae606de0b1f82ca888b6772ea89e Author: Guillem Jover <[email protected]> AuthorDate: Tue Feb 8 22:45:33 2022 +0100 dselect: Rework windows resize to be signal safe Remove all current explicit signal handling code for window resizes and instead rely on ncurses doing this for us, which is going to be async-signal-safe, instead of the current code which was not. Changelog: internal --- dselect/basecmds.cc | 2 +- dselect/baselist.cc | 68 +++++------------------------------------------- dselect/dselect.h | 8 ++---- dselect/methlist.cc | 15 +++++------ dselect/pkglist.cc | 15 +++++------ t/cppcheck/cppcheck.supp | 3 --- 6 files changed, 23 insertions(+), 88 deletions(-) diff --git a/dselect/basecmds.cc b/dselect/basecmds.cc index ef693d4c4..693784855 100644 --- a/dselect/basecmds.cc +++ b/dselect/basecmds.cc @@ -119,7 +119,7 @@ void baselist::kd_search() { echo(); if (wgetnstr(querywin,newsearchstring,sizeof(newsearchstring)-1) == ERR) searchstring[0]= 0; - raise(SIGWINCH); + resize_window(); noecho(); if (whatinfo_height) { touchwin(whatinfowin); refreshinfo(); } else if (info_height) { touchwin(infopad); refreshinfo(); } diff --git a/dselect/baselist.cc b/dselect/baselist.cc index fd96db3e1..ec8cf4da8 100644 --- a/dselect/baselist.cc +++ b/dselect/baselist.cc @@ -48,70 +48,14 @@ void mywerase(WINDOW *win) { wmove(win,0,0); } -baselist *baselist::signallist = nullptr; -void baselist::sigwinchhandler(int) { - int save_errno = errno; - struct winsize size; - debug(dbg_general, "baselist::sigwinchhandler(), signallist=%p", signallist); - baselist *p= signallist; - p->enddisplay(); - endwin(); initscr(); - if (ioctl(fileno(stdout), TIOCGWINSZ, &size) != 0) ohshite(_("ioctl(TIOCGWINSZ) failed")); - resizeterm(size.ws_row, size.ws_col); wrefresh(curscr); - p->startdisplay(); - if (doupdate() == ERR) ohshite(_("doupdate in SIGWINCH handler failed")); - errno = save_errno; -} - -static void cu_sigwinch(int, void **argv) { - struct sigaction *osigactp = static_cast<struct sigaction *>(argv[0]); - sigset_t *oblockedp = static_cast<sigset_t *>(argv[1]); - - if (sigaction(SIGWINCH, osigactp, nullptr)) - ohshite(_("failed to restore old SIGWINCH sigact")); - delete osigactp; - if (sigprocmask(SIG_SETMASK, oblockedp, nullptr)) - ohshite(_("failed to restore old signal mask")); - delete oblockedp; -} - -void -baselist::sigwinch_mask(int how) -{ - sigset_t sigwinchset; - sigemptyset(&sigwinchset); - sigaddset(&sigwinchset,SIGWINCH); - - int rc = sigprocmask(how, &sigwinchset, nullptr); - if (rc < 0) { - if (how == SIG_UNBLOCK) - ohshite(_("failed to unblock SIGWINCH")); - else - ohshite(_("failed to block SIGWINCH")); - } -} - void -baselist::setupsigwinch() +baselist::resize_window() { - struct sigaction *osigactp = new(struct sigaction); - sigset_t *oblockedp = new(sigset_t); - if (sigprocmask(0, nullptr, oblockedp)) - ohshite(_("failed to get old signal mask")); - if (sigaction(SIGWINCH, nullptr, osigactp)) - ohshite(_("failed to get old SIGWINCH sigact")); - - push_cleanup(cu_sigwinch, ~0, 2, osigactp, oblockedp); - - sigwinch_mask(SIG_BLOCK); - - struct sigaction nsigact; - memset(&nsigact,0,sizeof(nsigact)); - nsigact.sa_handler= sigwinchhandler; - sigemptyset(&nsigact.sa_mask); -//nsigact.sa_flags= SA_INTERRUPT; - if (sigaction(SIGWINCH, &nsigact, nullptr)) - ohshite(_("failed to set new SIGWINCH sigact")); + debug(dbg_general, "baselist::resize_window(), baselist=%p", this); + enddisplay(); + startdisplay(); + if (doupdate() == ERR) + ohshite(_("cannot update screen after window resize")); } void diff --git a/dselect/dselect.h b/dselect/dselect.h index e620f5af8..e3ec37603 100644 --- a/dselect/dselect.h +++ b/dselect/dselect.h @@ -97,12 +97,8 @@ protected: // If listpad is null, then we have not started to display yet, and // so none of the auto-displaying update routines need to display. - // SIGWINCH handling - void sigwinch_mask(int how); - void setupsigwinch(); - - static baselist *signallist; - static void sigwinchhandler(int); + // Window resize handling (via SIGWINCH). + void resize_window(); int nitems, ldrawnstart, ldrawnend, showinfo; int topofscreen, leftofscreen, cursorline; diff --git a/dselect/methlist.cc b/dselect/methlist.cc index 6cc280cf4..54382c546 100644 --- a/dselect/methlist.cc +++ b/dselect/methlist.cc @@ -157,19 +157,19 @@ quitaction methodlist::display() { debug(dbg_general, "methodlist[%p]::display()", this); - setupsigwinch(); startdisplay(); debug(dbg_general, "methodlist[%p]::display() entering loop", this); for (;;) { if (whatinfo_height) wcursyncup(whatinfowin); if (doupdate() == ERR) ohshite(_("doupdate failed")); - signallist= this; - sigwinch_mask(SIG_UNBLOCK); - do - response= getch(); - while (response == ERR && errno == EINTR); - sigwinch_mask(SIG_BLOCK); + do { + response = getch(); + if (response == KEY_RESIZE) { + resize_window(); + continue; + } + } while (response == ERR && errno == EINTR); if (response == ERR) ohshite(_("getch failed")); interp= (*bindings)(response); debug(dbg_general, "methodlist[%p]::display() response=%d interp=%s", @@ -178,7 +178,6 @@ quitaction methodlist::display() { (this->*(interp->mfn))(); if (interp->qa != qa_noquit) break; } - pop_cleanup(ehflag_normaltidy); // unset the SIGWINCH handler enddisplay(); debug(dbg_general, "methodlist[%p]::display() done", this); diff --git a/dselect/pkglist.cc b/dselect/pkglist.cc index 9ffe85517..54df0fc40 100644 --- a/dselect/pkglist.cc +++ b/dselect/pkglist.cc @@ -585,7 +585,6 @@ pkginfo **packagelist::display() { debug(dbg_general, "packagelist[%p]::display()", this); - setupsigwinch(); startdisplay(); if (!expertmode) @@ -596,12 +595,13 @@ pkginfo **packagelist::display() { if (whatinfo_height) wcursyncup(whatinfowin); if (doupdate() == ERR) ohshite(_("doupdate failed")); - signallist= this; - sigwinch_mask(SIG_UNBLOCK); - do - response= getch(); - while (response == ERR && errno == EINTR); - sigwinch_mask(SIG_BLOCK); + do { + response = getch(); + if (response == KEY_RESIZE) { + resize_window(); + continue; + } + } while (response == ERR && errno == EINTR); if (response == ERR) ohshite(_("getch failed")); interp= (*bindings)(response); @@ -611,7 +611,6 @@ pkginfo **packagelist::display() { (this->*(interp->pfn))(); if (interp->qa != qa_noquit) break; } - pop_cleanup(ehflag_normaltidy); // unset the SIGWINCH handler enddisplay(); if (interp->qa == qa_quitnochecksave || diff --git a/t/cppcheck/cppcheck.supp b/t/cppcheck/cppcheck.supp index 4d2741fc2..6a64e1be7 100644 --- a/t/cppcheck/cppcheck.supp +++ b/t/cppcheck/cppcheck.supp @@ -62,6 +62,3 @@ va_end_missing:lib/dpkg/parsehelp.c:68 // BUG: False positive, due to our local va_copy(). va_list_usedBeforeStarted:lib/compat/vasprintf.c - -// BUG: False positive, SIGWINCH is not a fatal signal. -unreachableCode:dselect/basecmds.cc:123 -- Dpkg.Org's dpkg

