Conversation
…rom htslib instead of the one in stdlib.h. Only the regular int version is available on Windows.
…compile on all platforms.
… with a more standards compliant mechanism. The problem was this test (sam.c line 2343): if (/.../ && fd->dispatcher) According to the pthreads standard, the pthread_t type should be considered opaque. On some platforms it is implemented as a struct rather than an integer, causing a compilation error. In addition, if a pthread_create call fails, the value of the thread identifier is undefined.
…nition; different linkage" errors on Windows.
|
Can you be a bit more specific about e46b03f which compiler is faulty? |
|
Re e46b03f: that's a C99ism that presumably the OP's compiler and/or compiler configuration doesn't like. It's just test code, so make it a Re os/rand.c: this file is #included into hts_os.c, which provides the |
Sure. It's the old msvc 2015 which isn't fully C99 compliant. It does not support variable-length arrays. But in this case the length wasn't really variable, so it was straightforward to change to a regular fixed-length array. |
I was choosing between a #define or an enum for the constant. Both work fine, but I tend to prefer the enum because it's more in-line with the code and has a tighter scope. If there is a preference for the #define alternative in this code base then I can of course change it. Just let me know. |
|
Your problem is with an old compiler that doesn't understand a (C99) array declaration. Other old compilers historically had trouble with array declarations that were anything other than a numeric literal, hence the suggestion to change it to the lowest common denominator, a The “should be treated as a header file” comment added is pretty opaque in isolation. it's pretty obvious that this is not an ordinary source file if you start from (I have comments about your other commits too, but much of it is contingent on what the maintainers' plans are re which Windows compilers they wish to |
|
Agreed our supported windows platform for building htslib is gcc (mingw iirc, but maybe msys - I always get them muddled up). However we do try to ensure people can program and link against htslib using a wider variety of compilers hence we sometimes make tweaks in header files to handle the idiosyncrases of broken compilers. (Plus in that regard it's really no different to all the extern C boilerplate for C++ users.) I think most of this doesn't come under that remit, but it's worth investigating if it doesn't break anything else. |
|
These changes should all be neutral to non-Windows users, except 5728bdc which introduces a change in how the dispatcher thread for multithreaded SAM reads and writes is initialized. The current code checks if the thread handle is null to find out if the thread has been created or not. The pthreads standard explicitly recommends against this usage pattern, as it is not portable and also because the thread handle is undefined if the call to pthread_create should fail. I.e. this should not be expected to work on linux/gcc either even if it compiles. |
|
Perhaps it would be better to split the PR into smaller ones? |
|
You are quite right that the pthread So it would certainly be worth pulling that one out into a separate PR, though the best starting point would be for @jkbonfield to confirm exactly what he meant to test on that line. The trouble with your current suggested fix is that it changes behaviour (or at least gives the impression of doing so). |
|
Sounds good. My interpretation of the code with the test ("if fd->dispatcher") is that is checks whether the dispatcher thread has been started or not. Because if it hasn't been started, and we're waiting for it to transition from CLOSE to CLOSED, then we're in for a long wait. What needs to be done instead is to check the return value of pthread_create() and save that information in the SAM_state somehow. That struct has a comment in it saying that changes to it can have severe performance penalties (caching lines?) so I thought it would be a better idea to slightly re-purpose the thread command/state enum to keep track of this information: introducing a new state to signal that the dispatcher thread has started. What do you say @jkbonfield -- would you like a new PR with only this fix, or would you rather take care of it yourself? |
|
That would be my interpretation too, but notice that a few lines later the same code calls Or it ought to be signalled thus — see PR #1154. |
|
I'd need to get my head around this code again! It's a bit of a can of worms, but that's not uncommon with complex thread locking. My main problem is it needs some time to fuzz all the combinations as experience has shown it's very easy to get wrong! |
|
I guess the check for Instead of setting Then we can use This may be easier to code up than describe... |
Part of the point of #1154 is that either removing this check is entirely safe or the subsequent
It may or may not be 😄, but note that in the current code |
|
It is true that the Easy way to test it is to add a deliberate return -2 into the code before the |
|
@jmarshall Hmm, yes. A specific "I started the thread" flag may in that case be a good idea. I was hoping that we could use the existing state machine in |
|
Would you like to keep this PR open for the discussion? Otherwise I'll close it, as it shouldn't be merged in its current form anyway. I'm planning to follow up with other PR's for the fixed-size array and similar. |
|
Leave it for the time being as it's a reminder that we still need to fix the threading issue. I'm leaning to just having a variable we set along side the thread pointer as it's the safest in terms of 100% understandable and easy to validate it does the same as the current code and doesn't have sneaky race conditions or gotchas with failing at key moments. I thought Rob was looking at this, but he's unavailable this week so I may do it quickly as a PR myself. |
Replaces samtools#1154 See also samtools#1153 It does this by the addition of a separate variable to do the boolean check on instead of fd->dispatcher itself. I deemed this easier to understand than overloading the interpretation of fd->h being set plus I'm unsure of the potential failure case in sam_hdr_fill_hrecs where fd->h has been set but we errored before creating the threads. Also improves error recovering in case of pthread creation failure, avoiding a false pthread_join later. Thanks to John Marshall and Anders Kaplan for identifying that issue.
Replaces samtools#1154 See also samtools#1153 It does this by the addition of a separate variable to do the boolean check on instead of fd->dispatcher itself. I deemed this easier to understand than overloading the interpretation of fd->h being set plus I'm unsure of the potential failure case in sam_hdr_fill_hrecs where fd->h has been set but we errored before creating the threads. Also improves error recovering in case of pthread creation failure, avoiding a false pthread_join later. Thanks to John Marshall and Anders Kaplan for identifying that issue.
Portability improvements made while getting HTSlib to build with msvc on Windows. Most of the changes are not specific to Windows but should also benefit other platforms.
The PR is split into commits which are all stand-alone and described individually.