Here's another one.
The progress meter in scp(1) and sftp(1) updates periodically, once
per second. But using alarm(3) to repeatedly rearm the signal causes
that update period to drift forward:
$ kdump -ts -R -f scp-current.ktrace.out
25343 scp 1672500224.844047 PSIG SIGALRM caught handler=0x239bf6ec750
mask=0<>
25343 scp 1.009691 PSIG SIGALRM caught handler=0x239bf6ec750 mask=0<>
25343 scp 1.000314 PSIG SIGALRM caught handler=0x239bf6ec750 mask=0<>
25343 scp 1.009971 PSIG SIGALRM caught handler=0x239bf6ec750 mask=0<>
25343 scp 1.009872 PSIG SIGALRM caught handler=0x239bf6ec750 mask=0<>
25343 scp 1.009831 PSIG SIGALRM caught handler=0x239bf6ec750 mask=0<>
25343 scp 1.000315 PSIG SIGALRM caught handler=0x239bf6ec750 mask=0<>
If we use setitimer(2), the update period does not drift:
$ kdump -ts -R -f scp-patched.ktrace.out
33053 scp 1672500345.413781 PSIG SIGALRM caught handler=0x9d45436b7f0
mask=0<>
33053 scp 1.000014 PSIG SIGALRM caught handler=0x9d45436b7f0 mask=0<>
33053 scp 1.000027 PSIG SIGALRM caught handler=0x9d45436b7f0 mask=0<>
33053 scp 1.000208 PSIG SIGALRM caught handler=0x9d45436b7f0 mask=0<>
33053 scp 0.999742 PSIG SIGALRM caught handler=0x9d45436b7f0 mask=0<>
33053 scp 1.000083 PSIG SIGALRM caught handler=0x9d45436b7f0 mask=0<>
33053 scp 1.000057 PSIG SIGALRM caught handler=0x9d45436b7f0 mask=0<>
33053 scp 1.000091 PSIG SIGALRM caught handler=0x9d45436b7f0 mask=0<>
33053 scp 0.999604 PSIG SIGALRM caught handler=0x9d45436b7f0 mask=0<>
33053 scp 1.000176 PSIG SIGALRM caught handler=0x9d45436b7f0 mask=0<>
ok?
Index: progressmeter.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/progressmeter.c,v
retrieving revision 1.50
diff -u -p -r1.50 progressmeter.c
--- progressmeter.c 23 Jan 2020 07:10:22 -0000 1.50
+++ progressmeter.c 31 Dec 2022 15:30:50 -0000
@@ -25,8 +25,10 @@
#include <sys/types.h>
#include <sys/ioctl.h>
+#include <sys/time.h>
#include <sys/uio.h>
+#include <err.h>
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
@@ -232,12 +234,13 @@ static void
sig_alarm(int ignore)
{
alarm_fired = 1;
- alarm(UPDATE_INTERVAL);
}
void
start_progress_meter(const char *f, off_t filesize, off_t *ctr)
{
+ struct itimerval itv = {{ UPDATE_INTERVAL, 0 }, { UPDATE_INTERVAL, 0 }};
+
start = last_update = monotime_double();
file = f;
start_pos = *ctr;
@@ -252,13 +255,17 @@ start_progress_meter(const char *f, off_
ssh_signal(SIGALRM, sig_alarm);
ssh_signal(SIGWINCH, sig_winch);
- alarm(UPDATE_INTERVAL);
+ if (setitimer(ITIMER_REAL, &itv, NULL) == -1)
+ err(1, "setitimer");
}
void
stop_progress_meter(void)
{
- alarm(0);
+ struct itimerval zero = { 0 };
+
+ if (setitimer(ITIMER_REAL, &zero, NULL) == -1)
+ err(1, "setitimer");
if (!can_output())
return;