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/snapshots/SnapshotShardsService.java
import static org.elasticsearch.core.Strings.format;
/**
 * This service runs on data nodes and controls currently running shard snapshots on these nodes. It is responsible for
 * starting and stopping shard level snapshots.
 * See package level documentation of {@link org.elasticsearch.snapshots} for details.
 */
public class SnapshotShardsService extends AbstractLifecycleComponent implements ClusterStateListener, IndexEventListener {
    private static final Logger logger = LogManager.getLogger(SnapshotShardsService.class);
    private final ClusterService clusterService;
    private final IndicesService indicesService;
    private final RepositoriesService repositoriesService;
    private final TransportService transportService;
    private final ThreadPool threadPool;
    private final Map<Snapshot, Map<ShardId, IndexShardSnapshotStatus>> shardSnapshots = new HashMap<>();
    
    private final ResultDeduplicator<UpdateIndexShardSnapshotStatusRequest, Void> remoteFailedRequestDeduplicator;
    public SnapshotShardsService(
        Settings settings,
        ClusterService clusterService,
        RepositoriesService repositoriesService,
        TransportService transportService,
        IndicesService indicesService
    ) {
        this.indicesService = indicesService;
        this.repositoriesService = repositoriesService;
        this.transportService = transportService;
        this.clusterService = clusterService;
        this.threadPool = transportService.getThreadPool();
        this.remoteFailedRequestDeduplicator = new ResultDeduplicator<>(threadPool.getThreadContext());
        if (DiscoveryNode.canContainData(settings)) {