aboutsummaryrefslogtreecommitdiff
path: root/src/xz/mytime.c
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2023-01-26 18:29:17 +0200
committerLasse Collin <lasse.collin@tukaani.org>2023-01-27 19:37:47 +0200
commitff592c616eda274215b485cf1b8d34f060c9f3be (patch)
tree7c3141dc351c68803372e7bcae4a87e5d7dcb6a7 /src/xz/mytime.c
parentTranslations: Add Brazilian Portuguese translation of man pages. (diff)
downloadxz-ff592c616eda274215b485cf1b8d34f060c9f3be.tar.xz
xz: Add SIGTSTP handler for progress indicator time keeping.
This way, if xz is stopped the elapsed time and estimated time remaining won't get confused by the amount of time spent in the stopped state. This raises SIGSTOP. It's not clear to me if this is the correct way. POSIX and glibc docs say that SIGTSTP shouldn't stop the process if it is orphaned but this commit doesn't attempt to handle that. Search for SIGTSTP in section 2.4.3: https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
Diffstat (limited to 'src/xz/mytime.c')
-rw-r--r--src/xz/mytime.c56
1 files changed, 55 insertions, 1 deletions
diff --git a/src/xz/mytime.c b/src/xz/mytime.c
index 7e8a0749..0b0e2be7 100644
--- a/src/xz/mytime.c
+++ b/src/xz/mytime.c
@@ -20,7 +20,12 @@
uint64_t opt_flush_timeout = 0;
+#ifdef USE_SIGTSTP_HANDLER
+static volatile uint64_t start_time;
+#else
static uint64_t start_time;
+#endif
+
static uint64_t next_flush;
@@ -48,10 +53,49 @@ mytime_now(void)
}
+#ifdef USE_SIGTSTP_HANDLER
+extern void
+mytime_sigtstp_handler(int sig lzma_attribute((__unused__)))
+{
+ // Measure how long the process stays in the stopped state and add
+ // that amount to start_time. This way the the progress indicator
+ // won't count the stopped time as elapsed time and the estimated
+ // remaining time won't be confused by the time spent in the
+ // stopped state.
+ //
+ // FIXME? Is raising SIGSTOP the correct thing to do? POSIX.1-2017
+ // says that orphan processes shouldn't stop on SIGTSTP. So perhaps
+ // the most correct thing to do could be to revert to the default
+ // handler for SIGTSTP, unblock SIGTSTP, and then raise(SIGTSTP).
+ // It's quite a bit more complicated than just raising SIGSTOP though.
+ //
+ // The difference between raising SIGTSTP vs. SIGSTOP can be seen on
+ // the shell command line too by running "echo $?" after stopping
+ // a process but perhaps that doesn't matter.
+ const uint64_t t = mytime_now();
+ raise(SIGSTOP);
+ start_time += mytime_now() - t;
+ return;
+}
+#endif
+
+
extern void
mytime_set_start_time(void)
{
+#ifdef USE_SIGTSTP_HANDLER
+ // Block the signals when accessing start_time so that we cannot
+ // end up with a garbage value. start_time is volatile but access
+ // to it isn't atomic at least on 32-bit systems.
+ signals_block();
+#endif
+
start_time = mytime_now();
+
+#ifdef USE_SIGTSTP_HANDLER
+ signals_unblock();
+#endif
+
return;
}
@@ -59,7 +103,17 @@ mytime_set_start_time(void)
extern uint64_t
mytime_get_elapsed(void)
{
- return mytime_now() - start_time;
+#ifdef USE_SIGTSTP_HANDLER
+ signals_block();
+#endif
+
+ const uint64_t t = mytime_now() - start_time;
+
+#ifdef USE_SIGTSTP_HANDLER
+ signals_unblock();
+#endif
+
+ return t;
}