When a shard is to be snapshotted, we acquire a store ref (wrapped in an index commit) and then enqueue the shard snapshot task for execution by the repository:

https://github.com/elastic/elasticsearch/blob/b124763772748d8993911e4a7ba94b17472a9539/server/src/main/java/org/elasticsearch/snapshots/SnapshotShardsService.java#L369-L384

If the shard is closed while its snapshot is in the queue then it looks like we do not release the store ref promptly. Instead, we keep hold of it until it reaches the front of the queue, which could be many minutes later. During this time the shard cannot fully shut down and release the shard lock, leading to a `ShardLockObtainFailedException` being thrown on attempts to reinitialise the shard.
server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java
+ previousWriterInfo.v2()
                + "] at generation ["
                + previousWriterInfo.v1()
                + "].";
    }
    /**
     * Marks the repository as corrupted. This puts the repository in a state where its tracked value 
     * {@link RepositoryMetadata#pendingGeneration()} is unchanged while its value  {@link RepositoryMetadata#generation()} is set to
     * {@link RepositoryData#CORRUPTED_REPO_GEN}. In this state, the repository can not be used any longer and must be removed and
     * recreated after the problem that lead to it being marked as corrupted has been fixed.
     *
     * @param corruptedGeneration generation that failed to load because the index file was not found but that should have loaded
     * @param originalException   exception that lead to the failing to load the {@code index-N} blob
     * @param listener            listener to invoke once done
     */
    private void markRepoCorrupted(long corruptedGeneration, Exception originalException, ActionListener<Void> listener) {
        assert corruptedGeneration != RepositoryData.UNKNOWN_REPO_GEN;
        assert bestEftConsistency == false;
        logger.warn(() -> "Marking repository [" + metadata.name() + "] as corrupted", originalException);
        submitUnbatchedTask(
            "mark repository corrupted [" + metadata.name() + "][" + corruptedGeneration + "]",
            new ClusterStateUpdateTask() {
                @Override
                public ClusterState execute(ClusterState State) {
                    final RepositoriesMetadata state = State.metadata().custom(RepositoriesMetadata.TYPE);
                    final RepositoryMetadata repoState = state.repository(metadata.name());
                    if (repoState.generation() != corruptedGeneration) {
                        throw new IllegalStateException(
                            "Tried to mark repo generation ["
                                + corruptedGeneration