Fix CancellationTokenRegistration.Unregister race condition (#309)
There's a race condition that exists if multiple threads are accessing the same CancellationTokenRegistration field, with one Unregistering and zero'ing out the field while another Unregisters. We shouldn't ever be in a situation where we have a non-null node and a 0 id, but due to struct tearing we can end up in that exact situation inside of Unregister (if the thread zero'ing out the struct succeeded in zero'ing out the id but we still read a valid node). If the node was then already unregistered, it will contain 0 for its id, in which case we'll see that the ids match and assume that means the node is still in the list. At that point we proceed to dereference nodes in the list and null ref.
The fix is simple: rather than just asserting that we'll never get 0, explicitly check for 0 and return if it is.