emscripten-core / emscripten

Emscripten: An LLVM-to-WebAssembly Compiler
Other
25.81k stars 3.31k forks source link

Asyncify returns immediately even when called indirectly #12299

Open Enfis opened 4 years ago

Enfis commented 4 years ago

Hello, I have some problems with Asyncify, let's go straight to the code:

In Bindings.h:

    class Factory
    {
    public:
      Factory ();
      IDecompress* NewDecompressor ();
      int GetLastError ();

    private:
      int last_error;
    };

In Bindings.cpp:

    IDecompress* Factory::NewDecompressor ()
    {
      // StdIO* my_io = new StdIO ("...");
      //
      // Where StdIO uses standard IO library and virtual file system (via "--preload-file")
      //
      // ** WORKS FINE **
      //

      CppIO* my_io = new CppIO ("source-file", 0); // CppIO uses Asyncify.handleSleep()

      IDecompress* ret = CreateDecompressor (my_io, &last_error);
      printf ("NewDecompressor = %d\r\n", ret);
      return ret;
    }

In Bindings.idl:

    interface IDecompress
    {
    };

    interface Factory
    {
      void Factory ();
      IDecompress NewDecompressor ();
      long GetLastError ();
    };

In index.html/Bindings.js:

    var factory = new Module.Factory ();
    console.log ("factory:");
    console.log (factory);
     // 
     // Code above is fine!
     //

    var decompressEx = factory.NewDecompressor ();
    console.log ("decompressEx:");
    console.log (decompressEx);
     // 
     // Code above return decompressEx with ptr: 0
     //
ERROR

CreateDecompressor function strongly uses CppIO class. Inside CppIO class, all the reads are made via Asyncify.handleSleep(). CreateDecompressor works fine, calls are made synchronously the problems is JavaScript that doesn't "wait until" CreateDecompressor() is returned.

Compiled with:

python webidl_binder.py Bindings.idl WebIDL

emcc -O0 -std=c++98 --post-js WebIDL.js -s WASM -s WASM_BIGINT -s ENVIRONMENT=web -s ASYNCIFY -s "ASYNCIFY_IMPORTS=['read_file_chunk', 'get_file_size']" -s "EXPORTED_FUNCTIONS=['_CreateDecompressor']" -o Bindings.js --preload-file injectedFiles\ Bindings.cpp WebIDL-Wrapper.cpp

What I'm doing wrong? Thank you (I'm an enscripten newbyte, please have mercy on me 😅)

PS - "read_file_chunk" is the Asyncify function, the project doesn't work (js code invoked from index.html returns immediately) even with the simplest form:

EM_JS (void, read_file_chunk, (char *id, int index, long long position, unsigned int length, void* destination), 
{
    Asyncify.handleSleep (function (wakeUp)
    {
        console.log ("BEFORE read_file_chunk");
        setTimeout (wakeUp, 1);
        console.log ("AFTER read_file_chunk");
    });
});
curiousdannii commented 4 years ago

Sounds like a duplicate of #12295

Enfis commented 4 years ago

Sounds like a duplicate of #12295

I was using version 2.0.1, now switched to latest 2.0.4 : both give the same problem 😥

sbc100 commented 4 years ago

Yes, looks like a duplicate of #12295. Hopefully its already been fixed in #12273. You you try emsdk update-tags && emsdk install tot?

Maybe lets close this in as duplicate?

kleisauke commented 4 years ago

AFAIK, only the versions 2.0.3 and 2.0.4 are affected of the bug mentioned in #12295. I'm not sure if 2.0.1 also has this issue.

@Enfis Could you try removing the -s WASM_BIGINT linker flag? Perhaps the combination of Asyncify + WASM_BIGINT causes this issue.

Enfis commented 4 years ago

AFAIK, only the versions 2.0.3 and 2.0.4 are affected of the bug mentioned in #12295. I'm not sure if 2.0.1 also has this issue.

@Enfis Could you try removing the -s WASM_BIGINT linker flag? Perhaps the combination of Asyncify + WASM_BIGINT causes this issue.

Removed the -s WASMBIGINT and still no luck 😣 Cpp code works just fine, because some milliseconds after the evil ptr: 0_ message returned, in console log I got:

NewDecompressor = 5305040

So a new instance of IDecompress has been allocated correctly with its pointer returned. The problem is on JavaScript side ... NewDecompressor() returns immediately with NULL when invoked.

Anyhow, installed the tot upstream and it doesn't fix:

git pull
emsdk update-tags
emsdk install tot
emsdk activate tot
emsdk_env

And on first compilation:

shared:INFO: (Emscripten: config changed, clearing cache)
shared:INFO: (Emscripten: Running sanity checks)

cache:INFO: generating system library: libc.a... (this will be cached in "E:\emsdk\upstream\emscripten\cache\wasm\libc.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libcompiler_rt.a... (this will be cached in "E:\emsdk\upstream\emscripten\cache\wasm\libcompiler_rt.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libc++-noexcept.a... (this will be cached in "E:\emsdk\upstream\emscripten\cache\wasm\libc++-noexcept.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libc++abi-noexcept.a... (this will be cached in "E:\emsdk\upstream\emscripten\cache\wasm\libc++abi-noexcept.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libdlmalloc.a... (this will be cached in "E:\emsdk\upstream\emscripten\cache\wasm\libdlmalloc.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libpthread_stub.a... (this will be cached in "E:\emsdk\upstream\emscripten\cache\wasm\libpthread_stub.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libc_rt_wasm.a... (this will be cached in "E:\emsdk\upstream\emscripten\cache\wasm\libc_rt_wasm.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: libsockets.a... (this will be cached in "E:\emsdk\upstream\emscripten\cache\wasm\libsockets.a" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system asset: generated_struct_info.json... (this will be cached in "E:\emsdk\upstream\emscripten\cache\wasm\generated_struct_info.json" for subsequent builds)
cache:INFO:  - ok
sbc100 commented 4 years ago

Can you confirm that it was indeed #12150 that broke you? e.g. checkout emscripten from git and sync to the revision right before this and see if that fixes your issue? Then confirm that sync to this revision breaks you?

Enfis commented 4 years ago

Can you confirm that it was indeed #12150 that broke you? e.g. checkout emscripten from git and sync to the revision right before this and see if that fixes your issue? Then confirm that sync to this revision breaks you?

Tested with 2.0.2, 2.0.1, 2.0.4 (latest) and tot : none works 🙄 (and fix #12150 is only 12 days old)

I've tried everything: removing WASM_BIGINT, removing almost all function parameters, oversimplifying WebIDL file, now there's only 1 Asyncify function and has been reduced to this one:

EM_JS (void, read_file_chunk, (), 
{
    Asyncify.handleSleep (function (wakeUp)
    {
        setTimeout (wakeUp, 500);
    });
});

And it is used by this C++ method:

int CppIO::Read (void * pBuffer, unsigned int nBytesToRead, unsigned int * pBytesRead)
{
// 
//  Uncommenting this line will break the program:
//
//   read_file_chunk ();
//
    *pBytesRead = fread (pBuffer, 1, nBytesToRead, handle);
    return 0;
}

When "_read_filechunk" is called, the program breaks, commenting read_file_chunk(), as above, and everything works perfectly as it should!!!

Immagine 2020-09-22 190255
sbc100 commented 4 years ago

Ah so this must be different issue then.

@Enfis, did you ever have this working? (under what emsdk version?)

Enfis commented 4 years ago

Ah so this must be different issue then.

@Enfis, did you ever have this working? (under what emsdk version?)

It never worked (using Asyncify)

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because there has been no activity in the past year. It will be closed automatically if no further activity occurs in the next 30 days. Feel free to re-open at any time if this issue is still relevant.