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;

Reply via email to