[GH-ISSUE #250] Panic from fetch.rs for a certain track and file format #169

Closed
opened 2026-02-27 19:29:13 +03:00 by kerem · 1 comment
Owner

Originally created by @ashthespy on GitHub (Sep 18, 2018).
Original GitHub issue: https://github.com/librespot-org/librespot/issues/250

The following track spotify:track:4NYe98w8kYWN2BMhiUIuzq with 320 bitrate (FileFormat::OGG_VORBIS_320 -- FileId("4310bb8d969082b6c2f64fb59de5d1871086a536")), leads to a panic from fetch.rs.

There seems to be some issue with the assert!(new_index < self.shared.chunk_count); check for this particular track.

FWIW - changing the < to <= avoids this panic - but I haven't looked into detail behind the reasoning for the assertion - Any ideas?

Added a few debug print statements, namely:

diff --git a/audio/src/fetch.rs b/audio/src/fetch.rs
index e5e461a..468aead 100644
--- a/audio/src/fetch.rs
+++ b/audio/src/fetch.rs
@@ -278,6 +278,7 @@ impl Future for AudioFileFetch {
                 Ok(Async::Ready(Some(offset))) => {
                     progress = true;
                     let index = offset as usize / CHUNK_SIZE;
+                    info!("Requesting seek_rx index {} for offest {}" , index, offset);
                     self.download(index);
                 }
                 Ok(Async::NotReady) => (),
@@ -309,6 +310,8 @@ impl Future for AudioFileFetch {
                     }
 
                     let new_index = (self.index + 1) % self.shared.chunk_count;
+                    info!("Requesting data_rx index {}",new_index);

INFO:librespot_playback::player: Loading track "Sito To" with Spotify URI "spotify:track:4NYe98w8kYWN2BMhiUIuzq"
INFO:librespot_playback::player: File :: Some(FileId("4310bb8d969082b6c2f64fb59de5d1871086a536"))
INFO:librespot_audio::fetch: Requesting seek_rx index 0 for offest 144
INFO:librespot_audio::fetch: Requesting data_rx index 1
INFO:librespot_audio::fetch: Requesting seek_rx index 0 for offest 167
INFO:librespot_audio::lewton_decoder: absgp: 0
INFO:librespot_audio::fetch: Requesting seek_rx index 0 for offest 167
INFO:librespot_audio::fetch: Requesting seek_rx index 0 for offest 167
INFO:librespot_audio::fetch: Requesting seek_rx index 74 for offest 9699328
thread 'main' panicked at 'assertion failed: new_index < self.shared.chunk_count', audio/src/fetch.rs:232:9
Originally created by @ashthespy on GitHub (Sep 18, 2018). Original GitHub issue: https://github.com/librespot-org/librespot/issues/250 The following track `spotify:track:4NYe98w8kYWN2BMhiUIuzq` with 320 bitrate (`FileFormat::OGG_VORBIS_320` -- `FileId("4310bb8d969082b6c2f64fb59de5d1871086a536")`), leads to a panic from `fetch.rs`. There seems to be some issue with the [`assert!(new_index < self.shared.chunk_count);`](https://github.com/librespot-org/librespot/blob/431be9e847a584d374ec44e7c138525dd8fbb9d6/audio/src/fetch.rs#L232) check for this particular track. FWIW - changing the `<` to `<=` avoids this panic - but I haven't looked into detail behind the reasoning for the assertion - Any ideas? Added a few debug print statements, namely: ```diff diff --git a/audio/src/fetch.rs b/audio/src/fetch.rs index e5e461a..468aead 100644 --- a/audio/src/fetch.rs +++ b/audio/src/fetch.rs @@ -278,6 +278,7 @@ impl Future for AudioFileFetch { Ok(Async::Ready(Some(offset))) => { progress = true; let index = offset as usize / CHUNK_SIZE; + info!("Requesting seek_rx index {} for offest {}" , index, offset); self.download(index); } Ok(Async::NotReady) => (), @@ -309,6 +310,8 @@ impl Future for AudioFileFetch { } let new_index = (self.index + 1) % self.shared.chunk_count; + info!("Requesting data_rx index {}",new_index); ``` ```rust INFO:librespot_playback::player: Loading track "Sito To" with Spotify URI "spotify:track:4NYe98w8kYWN2BMhiUIuzq" INFO:librespot_playback::player: File :: Some(FileId("4310bb8d969082b6c2f64fb59de5d1871086a536")) INFO:librespot_audio::fetch: Requesting seek_rx index 0 for offest 144 INFO:librespot_audio::fetch: Requesting data_rx index 1 INFO:librespot_audio::fetch: Requesting seek_rx index 0 for offest 167 INFO:librespot_audio::lewton_decoder: absgp: 0 INFO:librespot_audio::fetch: Requesting seek_rx index 0 for offest 167 INFO:librespot_audio::fetch: Requesting seek_rx index 0 for offest 167 INFO:librespot_audio::fetch: Requesting seek_rx index 74 for offest 9699328 thread 'main' panicked at 'assertion failed: new_index < self.shared.chunk_count', audio/src/fetch.rs:232:9 ```
kerem 2026-02-27 19:29:13 +03:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@ashthespy commented on GitHub (Sep 21, 2018):

On further investigation, this happens because Seek is attempting to get a block past the EOF.
This seems to occur specifically for this track and format because it's size (9699328) is an integer multiple of CHUNK_SIZE.

INFO:librespot_playback::player: Loading track "Dodole" with Spotify URI "spotify:track:1RLJijwCvgIbvUuVgWuhVF"
INFO:librespot_playback::player: File :: Some(FileId("bfd9e9ea7f13faf0e1f03531859c2af83683300a")) :: Position 0
INFO:librespot_audio::fetch: AudioFileOpen::len 9499100[u64] 72.472[chunks] => 73[chunks]
INFO:librespot_playback::player: Track "Dodole" loaded
INFO:librespot_playback::player: Loading track "Sito To" with Spotify URI "spotify:track:4NYe98w8kYWN2BMhiUIuzq"
INFO:librespot_playback::player: File :: Some(FileId("4310bb8d969082b6c2f64fb59de5d1871086a536")) :: Position 0
INFO:librespot_audio::fetch: AudioFileOpen::len 9699328[u64] 74.000[chunks] => 74[chunks]
WARN:librespot_audio::fetch: Panictime: 0
WARN:librespot_audio::fetch: Trying to seek past EOF

I added a check to ensure this doesn't happen - but am unsure if that is the right place to do it.

diff --git a/audio/src/fetch.rs b/audio/src/fetch.rs
index e5e461a..0cce8f5 100644
--- a/audio/src/fetch.rs
+++ b/audio/src/fetch.rs
@@ -64,6 +64,13 @@ impl AudioFileOpenStreaming {
         write_file.set_len(size as u64).unwrap();
         write_file.seek(SeekFrom::Start(0)).unwrap();
 
+        info!("AudioFileOpen::len {}[u64] {:.3}[chunks] => {}[chunks]",
+                size as u64,
+                size as f64 / CHUNK_SIZE as f64,
+                chunk_count);
+        if chunk_count <= size/CHUNK_SIZE {
+            warn!("Panictime: {}", size % CHUNK_SIZE);
+        }
         let read_file = write_file.reopen().unwrap();
 
         let data_rx = self.data_rx.take().unwrap();
@@ -348,11 +355,16 @@ impl Read for AudioFileStreaming {
 impl Seek for AudioFileStreaming {
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
         self.position = try!(self.read_file.seek(pos));
+        // Do not seek past EOF
+        if (self.position as usize % CHUNK_SIZE) != 0  {
+            // Notify the fetch thread to get the correct block
+            // This can fail if fetch thread has completed, in which case the
+            // block is ready. Just ignore the error.
+            let _ = self.seek.unbounded_send(self.position);
+        } else {
+            warn!("Trying to seek past EOF");
+        }
 
-        // Notify the fetch thread to get the correct block
-        // This can fail if fetch thread has completed, in which case the
-        // block is ready. Just ignore the error.
-        let _ = self.seek.unbounded_send(self.position);
         Ok(self.position)
     }
 }
<!-- gh-comment-id:423574812 --> @ashthespy commented on GitHub (Sep 21, 2018): On further investigation, this happens because `Seek` is attempting to get a block past the `EOF`. This seems to occur specifically for this track and format because it's size (9699328) is an integer multiple of `CHUNK_SIZE`. ```rust INFO:librespot_playback::player: Loading track "Dodole" with Spotify URI "spotify:track:1RLJijwCvgIbvUuVgWuhVF" INFO:librespot_playback::player: File :: Some(FileId("bfd9e9ea7f13faf0e1f03531859c2af83683300a")) :: Position 0 INFO:librespot_audio::fetch: AudioFileOpen::len 9499100[u64] 72.472[chunks] => 73[chunks] INFO:librespot_playback::player: Track "Dodole" loaded INFO:librespot_playback::player: Loading track "Sito To" with Spotify URI "spotify:track:4NYe98w8kYWN2BMhiUIuzq" INFO:librespot_playback::player: File :: Some(FileId("4310bb8d969082b6c2f64fb59de5d1871086a536")) :: Position 0 INFO:librespot_audio::fetch: AudioFileOpen::len 9699328[u64] 74.000[chunks] => 74[chunks] WARN:librespot_audio::fetch: Panictime: 0 WARN:librespot_audio::fetch: Trying to seek past EOF ``` I added a check to ensure this doesn't happen - but am unsure if that is the right place to do it. ```diff diff --git a/audio/src/fetch.rs b/audio/src/fetch.rs index e5e461a..0cce8f5 100644 --- a/audio/src/fetch.rs +++ b/audio/src/fetch.rs @@ -64,6 +64,13 @@ impl AudioFileOpenStreaming { write_file.set_len(size as u64).unwrap(); write_file.seek(SeekFrom::Start(0)).unwrap(); + info!("AudioFileOpen::len {}[u64] {:.3}[chunks] => {}[chunks]", + size as u64, + size as f64 / CHUNK_SIZE as f64, + chunk_count); + if chunk_count <= size/CHUNK_SIZE { + warn!("Panictime: {}", size % CHUNK_SIZE); + } let read_file = write_file.reopen().unwrap(); let data_rx = self.data_rx.take().unwrap(); @@ -348,11 +355,16 @@ impl Read for AudioFileStreaming { impl Seek for AudioFileStreaming { fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { self.position = try!(self.read_file.seek(pos)); + // Do not seek past EOF + if (self.position as usize % CHUNK_SIZE) != 0 { + // Notify the fetch thread to get the correct block + // This can fail if fetch thread has completed, in which case the + // block is ready. Just ignore the error. + let _ = self.seek.unbounded_send(self.position); + } else { + warn!("Trying to seek past EOF"); + } - // Notify the fetch thread to get the correct block - // This can fail if fetch thread has completed, in which case the - // block is ready. Just ignore the error. - let _ = self.seek.unbounded_send(self.position); Ok(self.position) } } ```
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/librespot#169
No description provided.