Package: ttyrec
Version: 1:1.0.8-4
Severity: normal
Tag: patch

If using ttyplay -p to peek at a live shell session, you
may occasionally see it print:

fread: Success

Followed by possibly, some garbage.

I have been able to reproduce this problem about 4 times in 2 days.
Typing a lot of fast little shell commands seems the best way. If
you have trouble reproducing the problem, you can simulate it by
modifying ttyrec to sleep(1) between write_header and fwrite.

The problem occurs if ttyread is reading from the last record,
which is in the process of being written to the file. That write
is not atomic, so it's possible for the header to be written to
the file, and read by ttyread, before the payload gets written.
(It may also be possible for a partial payload, or even a
partial header to be seen by ttyread.) When this happens, the
fread will reach EOF and return 0.

One approach to fix the problem might be to make ttyplay use a
single fwrite to write both the header and the record payload.
Then it would make only one write() system call, and the chances
of a partial write being seen would be lower. However, maybe
still not zero? Up to the kernel.

My approach is to have ttyread record the starting file
position before it reads the header. Then when it notices
EOF, it can rewind back to before that read, so it will
work next time it's called.

-- System Information:
Debian Release: squeeze/sid
  APT prefers unstable
  APT policy: (500, 'unstable'), (500, 'testing'), (500, 'stable')
Architecture: i386 (i686)

Kernel: Linux 2.6.31-1-686 (SMP w/2 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages ttyrec depends on:
ii  libc6                         2.10.2-2   GNU C Library: Shared libraries

ttyrec recommends no packages.

ttyrec suggests no packages.

-- debconf-show failed

-- 
see shy jo
diff --git a/ttyplay.c b/ttyplay.c
index 787dfa9..f62168d 100644
--- a/ttyplay.c
+++ b/ttyplay.c
@@ -142,8 +142,14 @@ ttynowait (struct timeval prev, struct timeval cur, double speed)
 int
 ttyread (FILE *fp, Header *h, char **buf)
 {
+    fpos_t pos;
+    int can_seek=0;
+    if (fgetpos(fp, &pos) == 0) {
+	can_seek=1;
+    }
+
     if (read_header(fp, h) == 0) {
-	return 0;
+	goto err;
     }
 
     *buf = malloc(h->len);
@@ -152,9 +158,21 @@ ttyread (FILE *fp, Header *h, char **buf)
     }
 	
     if (fread(*buf, 1, h->len, fp) == 0) {
-	perror("fread");
+	goto err;
     }
     return 1;
+
+err:
+    if (feof(fp)) {
+	/* Short read. Seek back to before header, to set up for retry. */
+	if (can_seek) {
+	    fsetpos(fp, &pos);
+	}
+    }
+    else {
+	perror("fread");
+    }
+    return 0;
 }
 
 int

Attachment: signature.asc
Description: Digital signature

Reply via email to