Skip to content

Commit b108bb8

Browse files
committed
Fix concurrent update/view creation segfault
Signed-off-by: Andrew Stein <steinlink@gmail.com>
1 parent a2c800a commit b108bb8

3 files changed

Lines changed: 63 additions & 11 deletions

File tree

rust/perspective-python/perspective/tests/multi_threaded/test_multi_threaded.py

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
import random
1717
import threading
1818

19+
from random import sample
20+
from string import ascii_letters
21+
from threading import Thread
22+
from time import sleep
1923

2024
class TestServer(object):
2125
def test_sync_updates_with_loop_callback_are_sync(self):
@@ -86,9 +90,7 @@ def update(x):
8690
loop.close()
8791

8892
def test_concurrent_updates_with_limit_tables_are_threadsafe(self):
89-
# This is a tricky tune - at time of writing, 1000 is has a >50%
90-
# chance of triggering this o my dev machine
91-
TEST_ITERATIONS = 1000
93+
TEST_ITERATIONS = 100
9294
global running
9395
perspective_server = Server()
9496
client = perspective_server.new_local_client()
@@ -156,3 +158,43 @@ def run_perspective():
156158
thread2.start()
157159
thread1.join()
158160
thread2.join()
161+
162+
def test_concurrent_view_creation_with_updates_are_threadsafe(self):
163+
s = Server()
164+
schema = {
165+
"a": "string",
166+
"b": "string",
167+
"c": "string",
168+
}
169+
170+
group_bys = ["a", "b", "c"]
171+
c = s.new_local_client()
172+
t = c.table(schema, limit=10000)
173+
running = True
174+
175+
def gen_views():
176+
global running
177+
for _ in range(100):
178+
t.view(columns=list(schema.keys()), group_by=group_bys)
179+
sleep(0.01)
180+
running = False
181+
182+
def run_psp():
183+
global running
184+
while running:
185+
t.update(
186+
[
187+
{
188+
"a": "".join(sample(ascii_letters, 4)),
189+
"b": "".join(sample(ascii_letters, 4)),
190+
"c": "".join(sample(ascii_letters, 4)),
191+
}
192+
]
193+
)
194+
195+
thread1 = Thread(target=run_psp, daemon=True)
196+
thread2 = Thread(target=gen_views, daemon=True)
197+
thread1.start()
198+
thread2.start()
199+
thread1.join()
200+
thread2.join()

rust/perspective-server/cpp/perspective/src/cpp/context_two.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ void
508508
t_ctx2::column_sort_by(const std::vector<t_sortspec>& sortby) {
509509
PSP_TRACE_SENTINEL();
510510
PSP_VERBOSE_ASSERT(m_init, "touching uninited object");
511+
m_column_sortby = sortby;
511512
m_ctraversal->sort_by(m_config, sortby, *(ctree()));
512513
}
513514

@@ -577,6 +578,10 @@ t_ctx2::notify(const t_data_table& flattened) {
577578
if (!m_sortby.empty()) {
578579
sort_by(m_sortby);
579580
}
581+
582+
if (!m_column_sortby.empty()) {
583+
column_sort_by(m_column_sortby);
584+
}
580585
}
581586

582587
void
@@ -651,6 +656,10 @@ t_ctx2::notify(
651656
if (!m_sortby.empty()) {
652657
sort_by(m_sortby);
653658
}
659+
660+
if (!m_column_sortby.empty()) {
661+
column_sort_by(m_column_sortby);
662+
}
654663
}
655664

656665
t_uindex

rust/perspective-server/cpp/perspective/src/cpp/server.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,15 @@ make_context(
184184

185185
auto pool = table->get_pool();
186186
auto gnode = table->get_gnode();
187+
188+
if (!sortspec.empty()) {
189+
ctx2->sort_by(sortspec);
190+
}
191+
192+
if (!col_sortspec.empty()) {
193+
ctx2->column_sort_by(col_sortspec);
194+
}
195+
187196
pool->register_context(
188197
gnode->get_id(),
189198
name,
@@ -203,14 +212,6 @@ make_context(
203212
ctx2->set_depth(t_header::HEADER_COLUMN, column_pivots.size());
204213
}
205214

206-
if (!sortspec.empty()) {
207-
ctx2->sort_by(sortspec);
208-
}
209-
210-
if (!col_sortspec.empty()) {
211-
ctx2->column_sort_by(col_sortspec);
212-
}
213-
214215
return ctx2;
215216
}
216217

0 commit comments

Comments
 (0)