Skip to content

Commit ee8eb2d

Browse files
author
kasemir
committed
PVA client: Fix ConcurrentModificationException in search
`ChannelSearch.runSearches` used to re-use one `to_search` array list. By the time the submitted searches encode the channels from that list, it might get cleared and re-populated. Need to create a new one in each `runSearches` call. At same time removed some unnecessary casts.
1 parent 0518d3c commit ee8eb2d

File tree

1 file changed

+5
-8
lines changed

1 file changed

+5
-8
lines changed

core/pva/src/main/java/org/epics/pva/client/ChannelSearch.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -342,17 +342,14 @@ public synchronized void boost()
342342
}
343343
}
344344

345-
/** List of channels to search, re-used within runSearches */
346-
private final ArrayList<PVAChannel> to_search = new ArrayList<>();
347-
348345
/** Invoked by timer: Check searched channels for the next one to handle */
349346
@SuppressWarnings("unchecked")
350347
private void runSearches()
351348
{
352349
// Determine current search bucket
353350
final int current = current_search_bucket.getAndUpdate(i -> (i + 1) % search_buckets.size());
354351
// Collect channels to be searched while sync'ed
355-
to_search.clear();
352+
final ArrayList<SearchRequest.Channel> to_search = new ArrayList<>();
356353
synchronized (this)
357354
{
358355
final Set<SearchedChannel> bucket = search_buckets.get(current);
@@ -406,7 +403,7 @@ private void runSearches()
406403
int count = 0;
407404
while (start + count < to_search.size() && count < Short.MAX_VALUE-1)
408405
{
409-
final PVAChannel channel = to_search.get(start + count);
406+
final SearchRequest.Channel channel = to_search.get(start + count);
410407
int size = 4 + PVAString.getEncodedSize(channel.getName());
411408
if (payload + size < MAX_SEARCH_PAYLOAD)
412409
{
@@ -428,9 +425,9 @@ else if (count == 0)
428425
if (count == 0)
429426
break;
430427

431-
final List<PVAChannel> batch = to_search.subList(start, start + count);
432-
// PVAChannel extends SearchRequest.Channel, so use List<PVAChannel> as Collection<SR.Channel>
433-
search((Collection<SearchRequest.Channel>) (List<? extends SearchRequest.Channel>)batch);
428+
// Submit one batch from 'to_search'
429+
final List<SearchRequest.Channel> batch = to_search.subList(start, start + count);
430+
search(batch);
434431
start += count;
435432
}
436433
}

0 commit comments

Comments
 (0)