Add error check to bgzf_seek_common()#1896
Conversation
As per issue samtools#1889, multithreaded seeking was not checking the error status on return.
| } while (fp->mt->command != SEEK_DONE); | ||
|
|
||
| if (fp->mt->errcode) | ||
| return -1; |
There was a problem hiding this comment.
I think this should also do fp->errcode |= BGZF_ERR_IO and it might be good if bgzf_mt_seek() set mt‑>errcode to errno (instead of BGZF_ERR_IO) so that this could also restore errno in the caller.
Also maybe this should come after …‑>command = NONE and unlocking the mutex, but perhaps continue to not do the resetting of fp‑>block_*.
There was a problem hiding this comment.
Hi @jmarshall, I don't suppose you have a decent bit of code to test a seek error?
There was a problem hiding this comment.
I'm afraid not. As in, to make a seek error deterministically actually happen so that you can make a test case that exercises this handling code? I've always vaguely meant to write a LD_PRELOAD hack to inject I/O errors, but have never got around to it. But probably such things exist…
Possibly one could make an HTSlib plugin that did this without needing to have a test-only build of hfile.o… 🤔
| fp->mt->command = NONE; | ||
|
|
||
| if (fp->mt->errcode) { | ||
| fp->errcode |= BGZF_ERR_IO; |
There was a problem hiding this comment.
Also errno = fp->mt->errcode to propagate errno over to the calling thread (if this multithreading works the way I assume it does!).
|
For purposes of repeating this experiment: Testing by generating a set of ranges: I now have a simple LD_PRELOAD lseek implementation that can generate errors. We can run it with no errors and see the seeks happening: Or we can introduce seek failues: The Edit: not incorrect, just highly misleading. It's a virtual offset which is a combination of compressed and uncompressed. It's (59306281<<16)+49163. It should probably say "failed to seek to virtual offset". |
|
Small improvement to above, if we're using dlsym we don't need to find the C library. On GNU we can define -D_GNU_SOURCE to enable RTLD_NEXT and just do: I remembered my horrifically scary "nitrous" command and saw this in there :). It replaced all open/close ,read/write/seek, etc with mmap and memcpys for super-fast I/O on any command, via LD_PRELOAD. Scary stuff, but also (mostly) worked amazingly well. lol. (Also scary to see that was back in 2008) |
As per issue #1889, multithreaded seeking was not checking the error status on return.