Skip to content

Commit 4c187b6

Browse files
E1izabethMatvey16
andauthored
dbeaver/pro#3273 Fix potential deadlock during autocompletion, typing and parsing (dbeaver#35367)
Co-authored-by: Matvey16 <[email protected]>
1 parent 475c59a commit 4c187b6

File tree

1 file changed

+40
-36
lines changed

1 file changed

+40
-36
lines changed

plugins/org.jkiss.dbeaver.ui.editors.sql/src/org/jkiss/dbeaver/ui/editors/sql/semantics/SQLBackgroundParsingJob.java

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -171,51 +171,55 @@ public void dispose() {
171171
public SQLQueryCompletionContext obtainCompletionContext(int offset) {
172172
SQLScriptItemAtOffset scriptItem = null;
173173
Position requestPosition = new Position(offset);
174-
do {
175-
final long requestStamp = System.currentTimeMillis();
176-
CompletableFuture<Long> expectedParsingSessionFinishStamp;
177-
synchronized (this.syncRoot) {
178-
if (scriptItem == null || this.queuedForReparse.size() == 0) {
179-
scriptItem = this.context.findScriptItem(offset - 1);
180-
if (scriptItem != null) { // TODO consider statements separation which is ignored for now
181-
if (scriptItem.item.isDirty()) {
182-
// awaiting reparse, so proceed to release lock and wait for the job to finish, then retry
183-
} else {
184-
return this.prepareCompletionContext(scriptItem, requestPosition.getOffset());
185-
}
186-
} else {
187-
// no script items here, so fallback to offquery context
188-
break;
189-
}
190-
}
191-
174+
try {
175+
UIUtils.syncExec(() -> {
192176
try {
193177
assert this.document != null;
194178
this.document.addPosition(requestPosition);
195179
} catch (BadLocationException e) {
196180
log.error(e);
197181
throw new RuntimeException(e);
198182
}
199-
expectedParsingSessionFinishStamp = this.lastParsingFinishStamp;
200-
}
201-
202-
try {
203-
// job.join() cannot be used here because completion request is being submitted at before-change event,
204-
// when the job is not scheduled yet (so join returns immediately)
205-
// job.schedule() performed only after the series of keypresses at after-change event
206-
if (expectedParsingSessionFinishStamp.get() < requestStamp) {
183+
});
184+
do {
185+
final long requestStamp = System.currentTimeMillis();
186+
CompletableFuture<Long> expectedParsingSessionFinishStamp;
187+
synchronized (this.syncRoot) {
188+
if (scriptItem == null || this.queuedForReparse.size() == 0) {
189+
scriptItem = this.context.findScriptItem(offset - 1);
190+
if (scriptItem != null) { // TODO consider statements separation which is ignored for now
191+
if (scriptItem.item.isDirty()) {
192+
// awaiting reparse, so proceed to release lock and wait for the job to finish, then retry
193+
} else {
194+
return this.prepareCompletionContext(scriptItem, requestPosition.getOffset());
195+
}
196+
} else {
197+
// no script items here, so fallback to offquery context
198+
break;
199+
}
200+
}
201+
expectedParsingSessionFinishStamp = this.lastParsingFinishStamp;
202+
}
203+
204+
try {
205+
// job.join() cannot be used here because completion request is being submitted at before-change event,
206+
// when the job is not scheduled yet (so join returns immediately)
207+
// job.schedule() performed only after the series of keypresses at after-change event
208+
if (expectedParsingSessionFinishStamp.get() < requestStamp) {
209+
return SQLQueryCompletionContext.EMPTY;
210+
}
211+
} catch (InterruptedException | ExecutionException e) {
212+
break;
213+
}
214+
if (requestPosition.isDeleted()) {
207215
return SQLQueryCompletionContext.EMPTY;
208216
}
209-
} catch (InterruptedException | ExecutionException e) {
210-
break;
211-
}
212-
if (requestPosition.isDeleted()) {
213-
return SQLQueryCompletionContext.EMPTY;
214-
} else {
215-
this.document.removePosition(requestPosition);
216-
}
217-
} while (scriptItem != null);
218-
return SQLQueryCompletionContext.prepareOffquery(0);
217+
} while (scriptItem != null);
218+
return SQLQueryCompletionContext.prepareOffquery(0);
219+
}
220+
finally {
221+
UIUtils.syncExec(() -> this.document.removePosition(requestPosition));
222+
}
219223
}
220224

221225
@NotNull

0 commit comments

Comments
 (0)