Prevent wraparound error when encoding time in ALiS

Due to a rare race condition in stream::run() it may happen that time of
the first non-init event is slightly lower than time of the init event.
This only happens in high bandwidth streams when the stream consumer
(e.g. forwarder to asciinema server) re-subscribes to the stream.
This commit is contained in:
Marcin Kulik
2025-06-24 17:34:49 +02:00
parent dd2cba282b
commit bbb75a6a3f

View File

@@ -77,7 +77,7 @@ impl EventSerializer {
Output(id, time, text) => { Output(id, time, text) => {
let id_bytes = leb128::encode(id); let id_bytes = leb128::encode(id);
let time_bytes = leb128::encode(time - self.0); let time_bytes = leb128::encode(self.rel_time(time));
let text_len = text.len() as u32; let text_len = text.len() as u32;
let text_len_bytes = leb128::encode(text_len); let text_len_bytes = leb128::encode(text_len);
@@ -87,14 +87,12 @@ impl EventSerializer {
msg.extend_from_slice(&text_len_bytes); msg.extend_from_slice(&text_len_bytes);
msg.extend_from_slice(text.as_bytes()); msg.extend_from_slice(text.as_bytes());
self.0 = time;
msg msg
} }
Input(id, time, text) => { Input(id, time, text) => {
let id_bytes = leb128::encode(id); let id_bytes = leb128::encode(id);
let time_bytes = leb128::encode(time - self.0); let time_bytes = leb128::encode(self.rel_time(time));
let text_len = text.len() as u32; let text_len = text.len() as u32;
let text_len_bytes = leb128::encode(text_len); let text_len_bytes = leb128::encode(text_len);
@@ -104,14 +102,12 @@ impl EventSerializer {
msg.extend_from_slice(&text_len_bytes); msg.extend_from_slice(&text_len_bytes);
msg.extend_from_slice(text.as_bytes()); msg.extend_from_slice(text.as_bytes());
self.0 = time;
msg msg
} }
Resize(id, time, size) => { Resize(id, time, size) => {
let id_bytes = leb128::encode(id); let id_bytes = leb128::encode(id);
let time_bytes = leb128::encode(time - self.0); let time_bytes = leb128::encode(self.rel_time(time));
let cols_bytes = leb128::encode(size.0); let cols_bytes = leb128::encode(size.0);
let rows_bytes = leb128::encode(size.1); let rows_bytes = leb128::encode(size.1);
@@ -121,14 +117,12 @@ impl EventSerializer {
msg.extend_from_slice(&cols_bytes); msg.extend_from_slice(&cols_bytes);
msg.extend_from_slice(&rows_bytes); msg.extend_from_slice(&rows_bytes);
self.0 = time;
msg msg
} }
Marker(id, time, text) => { Marker(id, time, text) => {
let id_bytes = leb128::encode(id); let id_bytes = leb128::encode(id);
let time_bytes = leb128::encode(time - self.0); let time_bytes = leb128::encode(self.rel_time(time));
let text_len = text.len() as u32; let text_len = text.len() as u32;
let text_len_bytes = leb128::encode(text_len); let text_len_bytes = leb128::encode(text_len);
@@ -138,14 +132,12 @@ impl EventSerializer {
msg.extend_from_slice(&text_len_bytes); msg.extend_from_slice(&text_len_bytes);
msg.extend_from_slice(text.as_bytes()); msg.extend_from_slice(text.as_bytes());
self.0 = time;
msg msg
} }
Exit(id, time, status) => { Exit(id, time, status) => {
let id_bytes = leb128::encode(id); let id_bytes = leb128::encode(id);
let time_bytes = leb128::encode(time - self.0); let time_bytes = leb128::encode(self.rel_time(time));
let status_bytes = leb128::encode(status.max(0) as u64); let status_bytes = leb128::encode(status.max(0) as u64);
let mut msg = vec![b'x']; let mut msg = vec![b'x'];
@@ -153,10 +145,16 @@ impl EventSerializer {
msg.extend_from_slice(&time_bytes); msg.extend_from_slice(&time_bytes);
msg.extend_from_slice(&status_bytes); msg.extend_from_slice(&status_bytes);
self.0 = time;
msg msg
} }
} }
} }
fn rel_time(&mut self, time: u64) -> u64 {
let time = time.max(self.0);
let rel_time = time - self.0;
self.0 = time;
rel_time
}
} }