Allow reproduction of the issue in 1156170 with pdfium_test.
Pump the message loop more frequently to expose GC concurency
issues. Does not fix the linked bug but rather makes it reproducible.
To avoid a number of new #ifdefs at various layers, encapsulate
the new logic in a std::function<> callback that can be passed
down to called functions.
Allows removal of a longstanding TODO() in foreground_task.in as
this test now completes as designed.
Bug: chromium:1156170
Change-Id: I82d95d71f31f9c427f330dbf08ab62ba94078079
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/76890
Reviewed-by: Hui Yingst <nigi@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc
index 91b4f90..26251fa 100644
--- a/samples/pdfium_test.cc
+++ b/samples/pdfium_test.cc
@@ -6,6 +6,7 @@
#include <stdlib.h>
#include <string.h>
+#include <functional>
#include <iterator>
#include <map>
#include <memory>
@@ -730,12 +731,13 @@
FPDF_FORMFILLINFO_PDFiumTest* form_fill_info,
const int page_index,
const Options& options,
- const std::string& events) {
+ const std::string& events,
+ const std::function<void()>& idler) {
FPDF_PAGE page = GetPageForIndex(form_fill_info, doc, page_index);
if (!page)
return false;
if (options.send_events)
- SendPageEvents(form, page, events);
+ SendPageEvents(form, page, events, idler);
if (options.save_images)
WriteImages(page, name.c_str(), page_index);
if (options.save_rendered_images)
@@ -795,9 +797,12 @@
}
FPDF_FFLDraw(form, bitmap.get(), page, 0, 0, width, height, 0, flags);
+ idler();
- if (!options.render_oneshot)
+ if (!options.render_oneshot) {
FPDF_RenderPage_Close(page);
+ idler();
+ }
int stride = FPDFBitmap_GetStride(bitmap.get());
void* buffer = FPDFBitmap_GetBuffer(bitmap.get());
@@ -861,7 +866,11 @@
}
FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_CLOSE);
+ idler();
+
FORM_OnBeforeClosePage(page, form);
+ idler();
+
return !!bitmap;
}
@@ -869,7 +878,8 @@
const char* buf,
size_t len,
const Options& options,
- const std::string& events) {
+ const std::string& events,
+ const std::function<void()>& idler) {
TestLoader loader({buf, len});
FPDF_FILEACCESS file_access = {};
@@ -1013,14 +1023,17 @@
}
}
if (ProcessPage(name, doc.get(), form.get(), &form_callbacks, i, options,
- events)) {
+ events, idler)) {
++processed_pages;
} else {
++bad_pages;
}
+ idler();
}
FORM_DoDocumentAAction(form.get(), FPDFDOC_AACTION_WC);
+ idler();
+
fprintf(stderr, "Processed %d pages.\n", processed_pages);
if (bad_pages)
fprintf(stderr, "Skipped %d bad pages.\n", bad_pages);
@@ -1163,6 +1176,7 @@
config.m_v8EmbedderSlot = 0;
config.m_pPlatform = nullptr;
+ std::function<void()> idler = []() {};
#ifdef PDF_ENABLE_V8
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
v8::StartupData snapshot;
@@ -1187,6 +1201,14 @@
FPDF_GetArrayBufferAllocatorSharedInstance());
isolate.reset(v8::Isolate::New(params));
config.m_pIsolate = isolate.get();
+
+ idler = [&platform, &isolate]() {
+ int task_count = 0;
+ while (v8::platform::PumpMessageLoop(platform.get(), isolate.get()))
+ ++task_count;
+ if (task_count)
+ fprintf(stderr, "Pumped %d tasks\n", task_count);
+ };
}
#endif // PDF_ENABLE_V8
@@ -1245,18 +1267,10 @@
}
}
}
- ProcessPdf(filename, file_contents.get(), file_length, options, events);
-#ifdef PDF_ENABLE_V8
- if (!options.disable_javascript) {
- int task_count = 0;
- while (v8::platform::PumpMessageLoop(platform.get(), isolate.get()))
- ++task_count;
-
- if (task_count)
- fprintf(stderr, "Pumped %d tasks\n", task_count);
- }
-#endif // PDF_ENABLE_V8
+ ProcessPdf(filename, file_contents.get(), file_length, options, events,
+ idler);
+ idler();
#ifdef ENABLE_CALLGRIND
if (options.callgrind_delimiters)
diff --git a/samples/pdfium_test_event_helper.cc b/samples/pdfium_test_event_helper.cc
index 1fe30c3..292d5a1 100644
--- a/samples/pdfium_test_event_helper.cc
+++ b/samples/pdfium_test_event_helper.cc
@@ -156,7 +156,8 @@
void SendPageEvents(FPDF_FORMHANDLE form,
FPDF_PAGE page,
- const std::string& events) {
+ const std::string& events,
+ const std::function<void()>& idler) {
auto lines = StringSplit(events, '\n');
for (const auto& line : lines) {
auto command = StringSplit(line, '#');
@@ -182,5 +183,6 @@
} else {
fprintf(stderr, "Unrecognized event: %s\n", tokens[0].c_str());
}
+ idler();
}
}
diff --git a/samples/pdfium_test_event_helper.h b/samples/pdfium_test_event_helper.h
index e823369..f03ddb9 100644
--- a/samples/pdfium_test_event_helper.h
+++ b/samples/pdfium_test_event_helper.h
@@ -5,6 +5,7 @@
#ifndef SAMPLES_PDFIUM_TEST_EVENT_HELPER_H_
#define SAMPLES_PDFIUM_TEST_EVENT_HELPER_H_
+#include <functional>
#include <string>
#include "public/fpdf_formfill.h"
@@ -12,6 +13,7 @@
void SendPageEvents(FPDF_FORMHANDLE form,
FPDF_PAGE page,
- const std::string& events);
+ const std::string& events,
+ const std::function<void()>& idler);
#endif // SAMPLES_PDFIUM_TEST_EVENT_HELPER_H_
diff --git a/testing/resources/javascript/foreground_task.in b/testing/resources/javascript/foreground_task.in
index b96917c..dd5444a 100644
--- a/testing/resources/javascript/foreground_task.in
+++ b/testing/resources/javascript/foreground_task.in
@@ -30,8 +30,7 @@
>>
stream
try {
- // TODO(tsepez): figure out why .then() doesn't fire.
- gc({type: 'major', execution: 'async'}).then(() => { app.alert('resolved') });
+ gc({type: 'major', execution: 'async'}).then(() => { app.alert('Resolved') });
app.alert('Posted');
} catch (e) {
app.alert('Error: ' + e);
diff --git a/testing/resources/javascript/foreground_task_expected.txt b/testing/resources/javascript/foreground_task_expected.txt
index a561e88..d40e100 100644
--- a/testing/resources/javascript/foreground_task_expected.txt
+++ b/testing/resources/javascript/foreground_task_expected.txt
@@ -1 +1,2 @@
Alert: Posted
+Alert: Resolved