[pacman-dev] Move cursor to the end of the screen at the SIGINT

Message ID 20201104010438.13068-1-anatol.pomozov@gmail.com
State New
Headers show
Series
  • [pacman-dev] Move cursor to the end of the screen at the SIGINT
Related show

Commit Message

Anatol Pomozov Nov. 4, 2020, 1:04 a.m. UTC
It requires exposing 'move cursor to the end' function in a pacman
header file. We use it as a chance to make naming of the cursor management
functions more consistent.

Note that there is still possibility of a race condition in the cursor
update logic. 'update cursor index variable' and 'send ASCII control
symbols to console' is not an atomic operation. So if an SIGINT is
received between these two action then cursor position is going to be
screwed.

Fixes FS#67973

Signed-off-by: Anatol Pomozov <anatol.pomozov@gmail.com>
---
 src/pacman/callback.c   | 24 +++++++++++-------------
 src/pacman/sighandler.c |  3 +++
 src/pacman/util.h       |  1 +
 3 files changed, 15 insertions(+), 13 deletions(-)

Comments

Allan McRae Nov. 26, 2020, 6:15 a.m. UTC | #1
On 4/11/20 11:04 am, Anatol Pomozov wrote:
> It requires exposing 'move cursor to the end' function in a pacman
> header file. We use it as a chance to make naming of the cursor management
> functions more consistent.
> 
> Note that there is still possibility of a race condition in the cursor
> update logic. 'update cursor index variable' and 'send ASCII control
> symbols to console' is not an atomic operation. So if an SIGINT is
> received between these two action then cursor position is going to be
> screwed.
> 
> Fixes FS#67973
> 
> Signed-off-by: Anatol Pomozov <anatol.pomozov@gmail.com>
> ---


Looks good.

As an aside, I'd like to boot those console functions into a separate
file at some stage.

Allan

Patch

diff --git a/src/pacman/callback.c b/src/pacman/callback.c
index 53518101..12ab952f 100644
--- a/src/pacman/callback.c
+++ b/src/pacman/callback.c
@@ -92,8 +92,6 @@  struct pacman_multibar_ui {
 
 struct pacman_multibar_ui multibar_ui = {0};
 
-static void cursor_goto_end(void);
-
 void multibar_move_completed_up(bool value) {
 	multibar_ui.move_completed_up = value;
 }
@@ -226,7 +224,7 @@  static int number_length(size_t n)
 void cb_event(alpm_event_t *event)
 {
 	if(config->print) {
-		cursor_goto_end();
+		console_cursor_move_end();
 		return;
 	}
 	switch(event->type) {
@@ -389,7 +387,7 @@  void cb_event(alpm_event_t *event)
 		case ALPM_EVENT_DB_RETRIEVE_FAILED:
 		case ALPM_EVENT_PKG_RETRIEVE_DONE:
 		case ALPM_EVENT_PKG_RETRIEVE_FAILED:
-			cursor_goto_end();
+			console_cursor_move_end();
 			flush_output_list();
 			on_progress = 0;
 			break;
@@ -694,7 +692,7 @@  static int dload_progressbar_enabled(void)
 }
 
 /* Goto the line that corresponds to num-th active download */
-static void cursor_goto_bar(int num)
+static void console_cursor_goto_bar(int num)
 {
 	if(num > multibar_ui.cursor_lineno) {
 		console_cursor_move_down(num - multibar_ui.cursor_lineno);
@@ -705,9 +703,9 @@  static void cursor_goto_bar(int num)
 }
 
 /* Goto the line *after* the last active progress bar */
-static void cursor_goto_end(void)
+void console_cursor_move_end(void)
 {
-	cursor_goto_bar(multibar_ui.active_downloads_num);
+	console_cursor_goto_bar(multibar_ui.active_downloads_num);
 }
 
 /* Returns true if element with the specified name is found, false otherwise */
@@ -849,7 +847,7 @@  static void dload_init_event(const char *filename, alpm_download_event_init_t *d
 	bar->rate = 0.0;
 	multibar_ui.active_downloads = alpm_list_add(multibar_ui.active_downloads, bar);
 
-	cursor_goto_end();
+	console_cursor_move_end();
 	printf(_(" %s downloading...\n"), filename);
 	multibar_ui.cursor_lineno++;
 	multibar_ui.active_downloads_num++;
@@ -894,7 +892,7 @@  static void dload_progress_event(const char *filename, alpm_download_event_progr
 	bar->total_size = data->total;
 	bar->xfered = data->downloaded;
 
-	cursor_goto_bar(index);
+	console_cursor_goto_bar(index);
 	draw_pacman_progress_bar(bar);
 	fflush(stdout);
 }
@@ -920,7 +918,7 @@  static void dload_complete_event(const char *filename, alpm_download_event_compl
 	bar->total_size = data->total;
 
 	if(data->result == 1) {
-		cursor_goto_bar(index);
+		console_cursor_goto_bar(index);
 		printf(_(" %s is up to date"), bar->filename);
 		/* The line contains text from previous status. Erase these leftovers. */
 		console_erase_line();
@@ -947,16 +945,16 @@  static void dload_complete_event(const char *filename, alpm_download_event_compl
 			multibar_ui.active_downloads->data = bar;
 			baritem->data = former_topbar;
 
-			cursor_goto_bar(index);
+			console_cursor_goto_bar(index);
 			draw_pacman_progress_bar(former_topbar);
 
 			index = 0;
 		}
 
-		cursor_goto_bar(index);
+		console_cursor_goto_bar(index);
 		draw_pacman_progress_bar(bar);
 	} else {
-		cursor_goto_bar(index);
+		console_cursor_goto_bar(index);
 		printf(_(" %s failed to download"), bar->filename);
 		console_erase_line();
 	}
diff --git a/src/pacman/sighandler.c b/src/pacman/sighandler.c
index fc4ea766..ff9c6ac4 100644
--- a/src/pacman/sighandler.c
+++ b/src/pacman/sighandler.c
@@ -53,6 +53,8 @@  static void _reset_handler(int signum)
  */
 static void soft_interrupt_handler(int signum)
 {
+	console_cursor_move_end();
+
 	if(signum == SIGINT) {
 		const char msg[] = "\nInterrupt signal received\n";
 		xwrite(STDERR_FILENO, msg, ARRAYSIZE(msg) - 1);
@@ -96,6 +98,7 @@  static void segv_handler(int signum)
 	sigset_t segvset;
 	const char msg[] = "\nerror: segmentation fault\n"
 		"Please submit a full bug report with --debug if appropriate.\n";
+	console_cursor_move_end();
 	xwrite(STDERR_FILENO, msg, sizeof(msg) - 1);
 	xwrite(STDOUT_FILENO, CURSOR_SHOW_ANSICODE,
 		sizeof(CURSOR_SHOW_ANSICODE) - 1);
diff --git a/src/pacman/util.h b/src/pacman/util.h
index c97048fb..ceaec6bd 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -85,6 +85,7 @@  void console_cursor_hide(void);
 void console_cursor_show(void);
 void console_cursor_move_up(unsigned int lines);
 void console_cursor_move_down(unsigned int lines);
+void console_cursor_move_end(void);
 /* Erases line from the current cursor position till the end of the line */
 void console_erase_line(void);