From d079eca24fa739e202b9145c7dcc8054b8165b77 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Mon, 24 Jun 2024 15:52:02 -0700 Subject: [PATCH] Remove non-working emscripten_fetch_wait / EMSCRIPTEN_FETCH_WAITABLE. NFC (#22138) This API hasn't worked since the fastcomp days, so I think its probably better to remove/deprecate it rather than try to make it work (perhaps using pthreads). --- ChangeLog.md | 3 ++ site/source/docs/api_reference/fetch.rst | 49 +----------------- src/generated_struct_info32.json | 5 +- src/generated_struct_info64.json | 1 - src/struct_info.json | 1 - system/include/emscripten/fetch.h | 14 +----- system/lib/fetch/emscripten_fetch.c | 55 +-------------------- test/fetch/test_fetch_sync_in_main_thread.c | 36 -------------- test/fetch/test_fetch_waitable.c | 38 -------------- test/test_browser.py | 11 ----- test/test_other.py | 1 - 11 files changed, 9 insertions(+), 205 deletions(-) delete mode 100644 test/fetch/test_fetch_sync_in_main_thread.c delete mode 100644 test/fetch/test_fetch_waitable.c diff --git a/ChangeLog.md b/ChangeLog.md index 12e00b30997b..a959fa99b44e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -20,6 +20,9 @@ See docs/process.md for more on how version tagging works. 3.1.62 (in development) ----------------------- +- The `EMSCRIPTEN_FETCH_WAITABLE` flag along with the `emscripten_fetch_wait` + API were marked a deprecated. These feature have not functions for several + years now. (#22138) - The internal `read_` function was removed. We now just use `readBinary` or `readAsync`. (#22080) - reference-types feature is now enabled by default in Emscripten, due to the diff --git a/site/source/docs/api_reference/fetch.rst b/site/source/docs/api_reference/fetch.rst index 3bc52826e4c2..e361b549ba24 100644 --- a/site/source/docs/api_reference/fetch.rst +++ b/site/source/docs/api_reference/fetch.rst @@ -200,55 +200,8 @@ emscripten_fetch() returns. - ``--proxy-to-worker`` + ``-pthread``: Synchronous Synchronous Fetch operations are available both on the main thread and pthreads. -Waitable Fetches -================ - -Emscripten Fetch operations can also run in a third mode, called a *waitable* -fetch. Waitable fetches start off as asynchronous, but at any point after the -fetch has started, the calling thread can issue a wait operation to either wait -for the completion of the fetch, or to just poll whether the fetch operation has -yet completed. The following code sample illustrates how this works. - -.. code-block:: cpp - - int main() { - emscripten_fetch_attr_t attr; - emscripten_fetch_attr_init(&attr); - strcpy(attr.requestMethod, "GET"); - attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY | EMSCRIPTEN_FETCH_WAITABLE; - emscripten_fetch_t *fetch = emscripten_fetch(&attr, "file.dat"); // Starts as asynchronous. - - EMSCRIPTEN_RESULT ret = EMSCRIPTEN_RESULT_TIMED_OUT; - while(ret == EMSCRIPTEN_RESULT_TIMED_OUT) { - /* possibly do some other work; */ - ret = emscripten_fetch_wait(fetch, 0/*milliseconds to wait, 0 to just poll, INFINITY=wait until completion*/); - } - // The operation has finished, safe to examine the fields of the 'fetch' pointer now. - - if (fetch->status == 200) { - printf("Finished downloading %llu bytes from URL %s.\n", fetch->numBytes, fetch->url); - // The data is now available at fetch->data[0] through fetch->data[fetch->numBytes-1]; - } else { - printf("Downloading %s failed, HTTP failure status code: %d.\n", fetch->url, fetch->status); - } - emscripten_fetch_close(fetch); - } - -Waitable fetches allow interleaving multiple tasks in one thread so that the -issuing thread can perform some other work until the fetch completes. - -.. note:: - - Waitable fetches are available only in certain build modes: - - - **No flags** or ``--proxy-to-worker``: Waitable fetches are not available. - - ``-pthread``: Waitable fetches are available on pthreads, but not - on the main thread. - - ``--proxy-to-worker`` + ``-pthread``: Waitable fetches are - available on all threads. - Tracking Progress -==================== +================= For robust fetch management, there are several fields available to track the status of an XHR. diff --git a/src/generated_struct_info32.json b/src/generated_struct_info32.json index 7197e8d47b7d..88102d443fa6 100644 --- a/src/generated_struct_info32.json +++ b/src/generated_struct_info32.json @@ -1488,9 +1488,8 @@ "withCredentials": 60 }, "emscripten_fetch_t": { - "__attributes": 112, - "__proxyState": 108, - "__size__": 208, + "__attributes": 108, + "__size__": 200, "data": 12, "dataOffset": 24, "id": 0, diff --git a/src/generated_struct_info64.json b/src/generated_struct_info64.json index 2a6378b9ffe1..dab20e11f25b 100644 --- a/src/generated_struct_info64.json +++ b/src/generated_struct_info64.json @@ -1489,7 +1489,6 @@ }, "emscripten_fetch_t": { "__attributes": 128, - "__proxyState": 124, "__size__": 272, "data": 24, "dataOffset": 40, diff --git a/src/struct_info.json b/src/struct_info.json index f2dd72af3e0a..2754543bcb5c 100644 --- a/src/struct_info.json +++ b/src/struct_info.json @@ -1101,7 +1101,6 @@ "readyState", "status", "statusText", - "__proxyState", "__attributes" ] }, diff --git a/system/include/emscripten/fetch.h b/system/include/emscripten/fetch.h index 07147de8adce..9099491c7387 100644 --- a/system/include/emscripten/fetch.h +++ b/system/include/emscripten/fetch.h @@ -61,9 +61,8 @@ extern "C" { // emscripten_fetch() while the operation is in progress. #define EMSCRIPTEN_FETCH_SYNCHRONOUS 64 -// If specified, it will be possible to call emscripten_fetch_wait() on the -// fetch to test or wait for its completion. #define EMSCRIPTEN_FETCH_WAITABLE 128 +#pragma clang deprecated(EMSCRIPTEN_FETCH_WAITABLE, "waitable fetch requests are no longer implemented") struct emscripten_fetch_t; @@ -190,8 +189,6 @@ typedef struct emscripten_fetch_t { // Specifies a human-readable form of the status code. char statusText[64]; - _Atomic uint32_t __proxyState; - // For internal use only. emscripten_fetch_attr_t __attributes; } emscripten_fetch_t; @@ -204,14 +201,7 @@ void emscripten_fetch_attr_init(emscripten_fetch_attr_t * _Nonnull fetch_attr); // given URL or from IndexedDB database. emscripten_fetch_t *emscripten_fetch(emscripten_fetch_attr_t * _Nonnull fetch_attr, const char * _Nonnull url); -// Synchronously blocks to wait for the given fetch operation to complete. This -// operation is not allowed in the main browser thread, in which case it will -// return EMSCRIPTEN_RESULT_NOT_SUPPORTED. Pass timeoutMSecs=infinite to wait -// indefinitely. If the wait times out, the return value will be -// EMSCRIPTEN_RESULT_TIMED_OUT. -// The onsuccess()/onerror()/onprogress() handlers will be called in the calling -// thread from within this function before this function returns. -EMSCRIPTEN_RESULT emscripten_fetch_wait(emscripten_fetch_t * _Nonnull fetch, double timeoutMSecs); +EMSCRIPTEN_RESULT emscripten_fetch_wait(emscripten_fetch_t * _Nonnull fetch, double timeoutMSecs) __attribute__((deprecated)); // Closes a finished or an executing fetch operation and frees up all memory. If // the fetch operation was still executing, the onerror() handler will be called diff --git a/system/lib/fetch/emscripten_fetch.c b/system/lib/fetch/emscripten_fetch.c index 8c454f225506..fbeaec7f28f5 100644 --- a/system/lib/fetch/emscripten_fetch.c +++ b/system/lib/fetch/emscripten_fetch.c @@ -147,57 +147,7 @@ emscripten_fetch_t* emscripten_fetch(emscripten_fetch_attr_t* fetch_attr, const } EMSCRIPTEN_RESULT emscripten_fetch_wait(emscripten_fetch_t* fetch, double timeoutMsecs) { -#if __EMSCRIPTEN_PTHREADS__ - if (!fetch) { - return EMSCRIPTEN_RESULT_INVALID_PARAM; - } - uint32_t proxyState = fetch->__proxyState; - if (proxyState == 2) { - // already finished. - return EMSCRIPTEN_RESULT_SUCCESS; - } - if (proxyState != 1) { - // the fetch should be ongoing? - return EMSCRIPTEN_RESULT_INVALID_PARAM; - } -#ifdef FETCH_DEBUG - emscripten_dbg("fetch: emscripten_fetch_wait.."); -#endif - if (timeoutMsecs <= 0) { - return EMSCRIPTEN_RESULT_TIMED_OUT; - } - while (proxyState == 1 /*sent to proxy worker*/) { - if (emscripten_is_main_browser_thread()) { - emscripten_err("fetch: emscripten_fetch_wait failed: main thread cannot block to wait for long periods of time! Migrate the application to run in a worker to perform synchronous file IO, or switch to using asynchronous IO."); - return EMSCRIPTEN_RESULT_FAILED; - } - int ret = emscripten_futex_wait(&fetch->__proxyState, proxyState, timeoutMsecs); - if (ret == -ETIMEDOUT) { - return EMSCRIPTEN_RESULT_TIMED_OUT; - } - proxyState = fetch->__proxyState; - } -#ifdef FETCH_DEBUG - emscripten_dbg("fetch: emscripten_fetch_wait done.."); -#endif - - if (proxyState != 2) { - return EMSCRIPTEN_RESULT_FAILED; - } - return EMSCRIPTEN_RESULT_SUCCESS; -#else - if (fetch->readyState >= STATE_DONE) { - return EMSCRIPTEN_RESULT_SUCCESS; // already finished. - } - if (timeoutMsecs == 0) { - return EMSCRIPTEN_RESULT_TIMED_OUT /*Main thread testing completion with sleep=0msecs*/; - } else { -#ifdef FETCH_DEBUG - emscripten_err("fetch: emscripten_fetch_wait() cannot stop to wait when building without pthreads!"); -#endif - return EMSCRIPTEN_RESULT_FAILED /*Main thread cannot block to wait*/; - } -#endif + return EMSCRIPTEN_RESULT_FAILED; } EMSCRIPTEN_RESULT emscripten_fetch_close(emscripten_fetch_t* fetch) { @@ -205,9 +155,6 @@ EMSCRIPTEN_RESULT emscripten_fetch_close(emscripten_fetch_t* fetch) { return EMSCRIPTEN_RESULT_SUCCESS; // Closing null pointer is ok, same as with free(). } -#if __EMSCRIPTEN_PTHREADS__ - fetch->__proxyState = 0; -#endif // This function frees the fetch pointer so that it is invalid to access it anymore. // Use a few key fields as an integrity check that we are being passed a good pointer to a valid // fetch structure, which has not been yet closed. (double close is an error) diff --git a/test/fetch/test_fetch_sync_in_main_thread.c b/test/fetch/test_fetch_sync_in_main_thread.c deleted file mode 100644 index da6259f22adb..000000000000 --- a/test/fetch/test_fetch_sync_in_main_thread.c +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2016 The Emscripten Authors. All rights reserved. -// Emscripten is available under two separate licenses, the MIT license and the -// University of Illinois/NCSA Open Source License. Both these licenses can be -// found in the LICENSE file. - -#include -#include -#include -#include -#include - -int main() -{ - emscripten_fetch_attr_t attr; - emscripten_fetch_attr_init(&attr); - attr.attributes = EMSCRIPTEN_FETCH_REPLACE | EMSCRIPTEN_FETCH_LOAD_TO_MEMORY | EMSCRIPTEN_FETCH_WAITABLE; - emscripten_fetch_t *fetch = emscripten_fetch(&attr, "gears.png"); - assert(fetch != 0); - memset(&attr, 0, sizeof(attr)); // emscripten_fetch() must be able to operate without referencing to this structure after the call. - printf("Main thread waiting for fetch to finish...\n"); - emscripten_fetch_wait(fetch, INFINITY); - printf("Main thread waiting for fetch to finish done...\n"); - assert(fetch->data != 0); - assert(fetch->numBytes > 0); - assert(fetch->totalBytes == fetch->numBytes); - assert(fetch->readyState == 4/*DONE*/); - assert(fetch->status == 200); - - uint8_t checksum = 0; - for(int i = 0; i < fetch->numBytes; ++i) - checksum ^= fetch->data[i]; - printf("Data checksum: %02X\n", checksum); - assert(checksum == 0x08); - emscripten_fetch_close(fetch); - return 0; -} diff --git a/test/fetch/test_fetch_waitable.c b/test/fetch/test_fetch_waitable.c deleted file mode 100644 index 0b296a29c6bf..000000000000 --- a/test/fetch/test_fetch_waitable.c +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 The Emscripten Authors. All rights reserved. -// Emscripten is available under two separate licenses, the MIT license and the -// University of Illinois/NCSA Open Source License. Both these licenses can be -// found in the LICENSE file. - -#include -#include -#include -#include - -int main() { - emscripten_fetch_attr_t attr; - emscripten_fetch_attr_init(&attr); - strcpy(attr.requestMethod, "GET"); - attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY | EMSCRIPTEN_FETCH_WAITABLE; - emscripten_fetch_t *fetch = emscripten_fetch(&attr, "myfile.dat"); // Starts as asynchronous. - - EMSCRIPTEN_RESULT ret = EMSCRIPTEN_RESULT_TIMED_OUT; - while (ret == EMSCRIPTEN_RESULT_TIMED_OUT) { - // possibly do some other work - // milliseconds to wait. 0 to just poll, INFINITY=wait until completion - ret = emscripten_fetch_wait(fetch, 1); - } - if (ret != EMSCRIPTEN_RESULT_SUCCESS) { - printf("Downloading %s failed: %d.\n", fetch->url, ret); - return 1; - } - // The operation has finished, safe to examine the fields of the 'fetch' pointer now. - - if (fetch->status != 200) { - printf("Downloading %s failed, HTTP failure status code: %d.\n", fetch->url, fetch->status); - return 1; - } - - printf("Finished downloading %llu bytes from URL %s.\n", fetch->numBytes, fetch->url); - emscripten_fetch_close(fetch); - return 0; -} diff --git a/test/test_browser.py b/test/test_browser.py index c122addaf706..28bd72a0daaa 100644 --- a/test/test_browser.py +++ b/test/test_browser.py @@ -4657,12 +4657,6 @@ def test_fetch_sync_xhr_in_proxy_to_worker(self): self.btest_exit('fetch/test_fetch_sync_xhr.cpp', args=['-sFETCH_DEBUG', '-sFETCH', '--proxy-to-worker']) - # Tests waiting on EMSCRIPTEN_FETCH_WAITABLE request from a worker thread - @unittest.skip("emscripten_fetch_wait relies on an asm.js-based web worker") - def test_fetch_sync_fetch_in_main_thread(self): - shutil.copyfile(test_file('gears.png'), 'gears.png') - self.btest_exit('fetch/test_fetch_sync_in_main_thread.cpp', args=['-sFETCH_DEBUG', '-sFETCH', '-sWASM=0', '-pthread', '-sPROXY_TO_PTHREAD']) - @disabled('https://github.com/emscripten-core/emscripten/issues/16746') def test_fetch_idb_store(self): self.btest_exit('fetch/test_fetch_idb_store.cpp', args=['-pthread', '-sFETCH', '-sPROXY_TO_PTHREAD']) @@ -4692,11 +4686,6 @@ def test_fetch_stream_async(self): create_file('myfile.dat', 'hello world\n' * 1000) self.btest_exit('fetch/test_fetch_stream_async.c', args=['-sFETCH']) - @disabled('waitable fetch operations were disabled when the fetch worker was removed') - def test_fetch_waitable(self): - create_file('myfile.dat', 'hello world\n' * 1000) - self.btest_exit('fetch/test_fetch_waitable.c', args=['-sFETCH']) - def test_fetch_persist(self): create_file('myfile.dat', 'hello world\n') self.btest_exit('fetch/test_fetch_persist.c', args=['-sFETCH']) diff --git a/test/test_other.py b/test/test_other.py index 59b56e0d70e2..474cd3dec1b3 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -13568,7 +13568,6 @@ def test_build_fetch_tests(self): self.build(test_file('fetch/test_fetch_idb_store.c')) self.build(test_file('fetch/test_fetch_stream_async.c')) self.build(test_file('fetch/test_fetch_sync.c')) - self.build(test_file('fetch/test_fetch_waitable.c')) self.build(test_file('fetch/test_fetch_progress.c')) def test_fetch_init_node(self):