Re: A call to std::rethrow_exception prints Abort() error

2023-08-23 Thread 'Mike Lischke' via emscripten-discuss
Hey Heejin,

> 
> I'm not sure if I understand the whole thread. For starters, 
> BailErrorStrategy::recover in the first post takes two arguments and it looks 
> you only provided one, making the second argument null automatically?

During the time this e-mail thread ran I tried a number of changes, to find a 
solution. The original code tried to get the exception ptr from C++ in JS and 
forwarded that to the recover() method. That didn't work, so I changed the code 
and passed no exception in, while on C++ side `std::current_exception()` was 
used to get this exception pointer. Also that failed, but a hint from Sam gave 
me the right idea (there can't be a current exception in C++, if no C++ 
exception was thrown **in C++**). That's why I ended up with passing the C++ 
exception that was thrown in JS to C++, where I could then do all the 
processing successfully.

> Also I don't understand what you mean by "JS incarnation of C++ exceptions" 
> either... 

In one of my mails I explained what I meant. It's about the JS object for a C++ 
exception class (or any C++ class, for that matter).

>> 
>>  
>>> - throw C++ exception in JS
>> 
>> I don't think it possible (or should be possible) to use a JS `throw` 
>> statement to throw C++ exception.. C++ exceptions must be thrown by the 
>> native `__cxa_throw` mechanism.  In order words even if you have a handle to 
>> C++ object you want to throw, I believe the only way to throw is to call 
>> back into native code to perform a C++ throw.
>> 
>> I could be wrong about this though.. @Heejin Ahn  
>> can probably say more on this.
> 
> You can do that for Wasm exceptions by using the JS API 
> .
> 
> An example of such code is in our JS library: 
> https://github.com/emscripten-core/emscripten/blob/9bb02c0182bcfc32450ea15d5be69eab494042df/src/library_exceptions.js#L328-L344
> This code does some string manipulation to make the stack trace tidy, but 
> what you need for creating an exception and throwing is just these lines:
> ```
> var e = new WebAssembly.Exception(getCppExceptionTag(), [ex], {traceStack: 
> true});
> throw e;
> ```
> I'm not sure you can do that for the old way of Emscripten exceptions. 

Well, I guess we have to make sure we talk about the same use cases. In my case 
I throw these exceptions in JS only to interrupt JS code, not C++ code. 
However, I have to know which exception was thrown from JS code in C++, as 
further handling depends on that (hence that call to `recover()` with the 
catched exception in JS). To recap, this is how it looks (and works) now:

catch (re) {
if (re instanceof RecognitionException) {
this.getErrorHandler().reportError(this, re);
this.getErrorHandler().recover(this, re);
} else {
throw re;
}
}

`re` is a sub class of the wrapped C++ `RecognitionException` and recover() 
will throw a nested exception in C++ as the final action, which is catched 
somewhere else.

>> 
> I'm also not sure why embind should be involved. By the way, Wasm exceptions 
> will not be represented as simple integer pointers in the JS world. They are 
> WebAssembly.Exception 
> objects.

Yes, I experimented with both variants (-fexceptions and -fwasm-exceptions), 
but I have no clear picture which one is better. However, the WebAssembly 
exceptions seem to require more work (getting information and manually delete 
them) and the documentation is pretty thin for either way.

Anyway, the discussion here is rather about how to make the `instanceof` 
operator work on a catched exception that was thrown in C++.

Thanks for all the insight!

Mike
-- 
www.soft-gems.net

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/emscripten-discuss/2582B3B4-4B82-4FFA-81DC-321016F74A4B%40googlemail.com.


Re: A call to std::rethrow_exception prints Abort() error

2023-08-23 Thread 'Mike Lischke' via emscripten-discuss
>> 
>> - throw JSError in JS
> 
> My JSError do you mean something that is the result of calling `new Error` in 
> JS?   I don't think that can or should interact at all with the C++ exception 
> handling mechanism.   I see them as two orthogonal systems and trying to mix 
> them or conflate them is likely to lead to trouble.

Right, right, this was just the initial step to find a common ground from which 
to go up in our discussion.

>> 
>> - throw C++ exception in JS
> 
> I don't think it possible (or should be possible) to use a JS `throw` 
> statement to throw C++ exception.. C++ exceptions must be thrown by the 
> native `__cxa_throw` mechanism.  In order words even if you have a handle to 
> C++ object you want to throw, I believe the only way to throw is to call back 
> into native code to perform a C++ throw.
> 
> I could be wrong about this though.. @Heejin Ahn  
> can probably say more on this.

For me it works. I have bound the RecognitionException (and many others, 
including std::exception) with embind and throw that in my JS code. It is 
catched in the catch() clause in JS and I can work with the exception, 
including sending it to C++ where it can be used to wrap it with 
`std::make_exception_ptr` and `std::rethrow_exception`. Great integration, I 
must say!

The only little thing that is missing is the wrapping of the exception class as 
"normal class handle", as it is done for the other C++ classes in JS, to allow 
things like checking the type using `instanceof`.

>> 
>> 
> I don't see why embind would need to be involved necessarily.  Not all 
> programs use embind, and its possible to refer to C++ object via simple 
> pointers in JS. 

That's certainly true, but my confusion with all the things required to make 
this work with embind is already huge. Please don't add to that with more 
options :-D

Thanks, 

Mike
-- 
www.soft-gems.net

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/emscripten-discuss/7F6534C2-FACD-423C-BBB1-DBB723212057%40googlemail.com.


Re: A call to std::rethrow_exception prints Abort() error

2023-08-22 Thread 'Mike Lischke' via emscripten-discuss
> 
> Taking a quick look at rethrow_exception, it looks like it calls `terminate` 
> if the `ptr` is NULL:
> 
> https://github.com/emscripten-core/emscripten/blob/097290ded2746c6ba703d556fd53b23e5aef760a/system/lib/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp#L66-L71
> 
> Can you trace the value of the `std::exception_ptr` you are trying to rethrow 
> to confirm?

That was spot on Sam! The error is thrown in JS, so calling 
`std::current_exception()` in C++ returns a null ptr. What I do now is to 
forward the thrown exception from JS (which is one of the C++ exceptions) and 
call std::make_exception_ptr to convert it to an exception pointer (to create a 
nested exception).

> 
> Regarding handling C++ exceptions in JS, I think you will always need to do 
> things like getExceptionMessage to unpack information if all you have is a 
> thrown object from C++. 

Well, the thrown error has its name set to the C++ exception, so what I do now 
is:

private isCancellationException(e: Error): boolean {
return e.name === "std::__nested";
}

Not really elegant, nor type safe, but it works.

> 
> Can you explain what you mean by "if I throw a C++ exception in its JS 
> incarnation".. what is a JS incarnation?

Sure. There are 4 ways you can throw an exception/error with wasm:

- throw JSError in JS
- throw C++ exception in C++
- throw C++ exception in JS
- throw a JS error in C++ (I believe, never tried that)

To throw a C++ exception in JS that exception must be bound as usual with 
embind (and that thrown JS error is the JS incarnation of the C++ exception). 
When you get an instance of a normal C++ class in JS, it represents such an 
embind/emval object (class handle). Not so for a C++ exception thrown in C++ 
but catched in JS. Check this out:

This is the JS object of the C++ exception thrown in C++:

std::__nested\nat ___resumeException 
(file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:1328:25)\n
at antlr4::BailErrorStrategy::recover(antlr4::Parser*, std::exception_ptr) 
(wasm://wasm/0507610a:wasm-function[2254]:0x414cb)\nat invoke_viii 
(file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:7667:29)\n
at antlr4::BailErrorStrategy::recover(antlr4::Parser*, 
antlr4::RecognitionException*) 
(wasm://wasm/0507610a:wasm-function[2257]:0x4161d)\nat 
emscripten::internal::MethodInvoker::invoke(void (antlr4::BailErrorStrategy::* 
const&)(antlr4::Parser*, antlr4::RecognitionException*), 
antlr4::BailErrorStrategy*, antlr4::Parser*, antlr4::RecognitionException*) 
(wasm://wasm/0507610a:wasm-function[205]:0xb1a1)\nat ClassHandle.BailE… …
excPtr:
4098424
name:
'std::__nested'
message:
''
stack:
'std::__nested\nat ___resumeException 
(file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:1328:25)\n
 <>at antlr4::BailErrorStrategy::recover(antlr4::Parser*, 
std::exception_ptr) (wasm://wasm/0507610a:wasm-function[2254]:0x414cb)\n <>
at invoke_viii 
(file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:7667:29)\n
 <>at antlr4::BailErrorStrategy::recover(antlr4::Parser*, 
antlr4::RecognitionException*) 
(wasm://wasm…r4wasm/benchmarks/mysql/generated/TypeScript/MySQLParser.ts:12448:40)\n
 <>at MySQLParser.selectStatement 
(file:///Volumes/Extern/Work/projects/antlr4wasm/benchmarks/mysql/generated/TypeScript/MySQLParser.ts:1:30)\n
 <>at MySQLParser.simpleStatement 
(file:///Volumes/Extern/Work/projects/antlr4wasm/benchmarks/mysql/generated/TypeScript/MySQLParser.ts:3283:30)\n
 <>at MySQLParser.query 
(file:///Volumes/Extern/Work/projects/antlr4wasm/benchmarks/mysql/generated/TypeScript/MySQLParser.ts:3140:46
 <>)'
[[Prototype]]:
EmscriptenEH

while the C++ exception, thrown in JS looks like this:

ClassHandle {$$: {…}}
$$:
{ptrType: RegisteredPointer, ptr: 4069744, count: {…}}
[[Prototype]]:
ClassHandle

The call stack for the first case is:

std::__nested
at ___resumeException 
(file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:1328:25)
at antlr4::BailErrorStrategy::recover(antlr4::Parser*, std::exception_ptr) 
(wasm://wasm/0507610a:wasm-function[2254]:0x414cb)
at invoke_viii 
(file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:7667:29)
at antlr4::BailErrorStrategy::recover(antlr4::Parser*, 
antlr4::RecognitionException*) 
(wasm://wasm/0507610a:wasm-function[2257]:0x4161d)
at emscripten::internal::MethodInvoker::invoke(void (antlr4::BailErrorStrategy::* 
const&)(antlr4::Parser*, antlr4::RecognitionException*), 
antlr4::BailErrorStrategy*, antlr4::Parser*, antlr4::RecognitionException*) 
(wasm://wasm/0507610a:wasm-function[205]:0xb1a1)
at ClassHandle.BailErrorStrategy$recover [as recover] (eval at newFunc 
(file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:5544:27),
 :11:1)
at MySQLParser.queryExpression 

Re: A call to std::rethrow_exception prints Abort() error

2023-08-21 Thread 'Mike Lischke' via emscripten-discuss
Hey Sam,

> 
> Can you share the link flags you are are using for your project?We know 
> this works in at least some cases because we have a test for it:
> 
> See:
> 
> https://github.com/emscripten-core/emscripten/blob/main/test/core/test_exceptions_primary.cpp
> 
> and:
> 
> https://github.com/emscripten-core/emscripten/blob/main/test/core/test_exceptions_primary.out
> 
> I imagine there is some issue with the settings you are using.
> 
> Do you get any kind of backtrace when you see the `Aborted(native code called 
> abort())` message?  Normally I would expect to see a backtrace?  Does happens 
> with you build with `-O0` vs `-O3`?  Any more information?

Sure, here's the stack:

Aborted(native code called abort())
antlr4-runtime-wasm.js:677
RuntimeError: Aborted(native code called abort())
at abort 
(file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:696:11)
at _abort 
(file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:6770:7)
at invoke_v 
(file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js::29)
at std::__terminate(void (*)()) 
(wasm://wasm/0503c22a:wasm-function[5703]:0xdaa23)
at std::terminate() (wasm://wasm/0503c22a:wasm-function[5701]:0xdaa06)
at std::rethrow_exception(std::exception_ptr) 
(wasm://wasm/0503c22a:wasm-function[3857]:0xb19ca)
at invoke_vi 
(file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:7645:29)
at antlr4::BailErrorStrategy::recover(antlr4::Parser*, std::exception_ptr) 
(wasm://wasm/0503c22a:wasm-function[2218]:0x405c6)
at invoke_viii 
(file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:7667:29)
at antlr4::BailErrorStrategy::recover(antlr4::Parser*) 
(wasm://wasm/0503c22a:wasm-function[2223]:0x40bc1)

And this is the build call:

em++ \
wasm/antlr4-runtime-wrapper.cpp \
antlr4-cpp-runtime/*.cpp\
antlr4-cpp-runtime/atn/*.cpp\
antlr4-cpp-runtime/dfa/*.cpp\
antlr4-cpp-runtime/internal/*.cpp\
antlr4-cpp-runtime/misc/*.cpp\
antlr4-cpp-runtime/support/*.cpp\
antlr4-cpp-runtime/tree/*.cpp\
antlr4-cpp-runtime/tree/pattern/*.cpp\
antlr4-cpp-runtime/tree/xpath/*.cpp\
-O3\
-std=c++17 -lembind -Iantlr4-cpp-runtime/ \
-o wasm/antlr4-runtime-wasm.js\
-s EXPORT_ES6=1\
-s WASM=1\
-s WASM_BIGINT=1\
-s ALLOW_MEMORY_GROWTH=1\
-s ASSERTIONS\
-fexceptions\
-g


I wonder why std::rethrow_exception calls std::__terminate in my code...

Btw. I saw that JS objects from exceptions thrown in C++ are different compared 
to all the other objects (no $$, no class handle etc). That makes it impossible 
to use `instanceof` to check for a particular exception type. I now have to 
check the exception name, which is a bit awkward. As you see I'm using JS 
exception support, not wasm exceptions, as the latter are a bit inconvenient 
with those tags to get details (I know there's getExceptionMessage, but that's 
not better than checking the JS exception object name).

On the other hand, if I throw a C++ exception in its JS incarnation, I get the 
normal object structure and `instanceof` works. Is this different behaviour 
intended?

For completeness I also tested with -swasm-exception and got this stack trace:

libc++abi: terminating
antlr4-runtime-wasm.js:1660
Aborted(native code called abort())
antlr4-runtime-wasm.js:677
RuntimeError: unreachable
at __trap (wasm://wasm/04f49f3e:wasm-function[5811]:0xb7307)
at ___trap 
(file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:7407:54)
at abort 
(file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:706:5)
at _abort 
(file:///Volumes/Extern/Work/projects/antlr4wasm/wasm/antlr4-runtime-wasm.js:6599:7)
at abort_message (wasm://wasm/04f49f3e:wasm-function[5680]:0xb53bd)
at demangling_terminate_handler() 
(wasm://wasm/04f49f3e:wasm-function[5681]:0xb54ed)
at std::__terminate(void (*)()) 
(wasm://wasm/04f49f3e:wasm-function[5703]:0xb56b9)
at std::terminate() (wasm://wasm/04f49f3e:wasm-function[5701]:0xb5692)
at std::rethrow_exception(std::exception_ptr) 
(wasm://wasm/04f49f3e:wasm-function[3815]:0x92fd7)
at antlr4::BailErrorStrategy::recover(antlr4::Parser*, std::exception_ptr) 
(wasm://wasm/04f49f3e:wasm-function[2178]:0x386ed)


Mike
-- 
www.soft-gems.net



Mike
-- 
www.soft-gems.net

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/emscripten-discuss/E09B6FEF-33E9-4E0F-95C1-F2A73CAD1EA3%40googlemail.com.


A call to std::rethrow_exception prints Abort() error

2023-08-19 Thread 'Mike Lischke' via emscripten-discuss
Hi,

In my library I have to catch errors in JS and let C++ do something with them. 
A typical catch block in JS looks like this:

catch (re) {
if (re instanceof RecognitionException) {
this.getErrorHandler().reportError(this, re);
this.getErrorHandler().recover(this);
} else {
throw re;
}
}

The call to `recover` prints this message, however (-s ASSERTION used with -O3):

Aborted(native code called abort())

The native code is:

void BailErrorStrategy::recover(Parser *recognizer, std::exception_ptr e) {
  ParserRuleContext *context = recognizer->getContext();
  do {
context->exception = e;
if (context->parent == nullptr)
  break;
context = static_cast(context->parent);
  } while (true);

  try {
std::rethrow_exception(e); // Throw the exception to be able to catch and 
rethrow nested.
  } catch (RecognitionException & /*inner*/) {
std::throw_with_nested(ParseCancellationException());
  }
}

I traced the execution to the `std::rethrow_exception` line, which ends this 
call prematurely with the above error. To see if it is just a different 
exception I added a catch(...) clause, but that is never executed, so to me it 
looks as if `std::rethrow_exception` is something that cannot be used in 
WebAssembly. Is that assumption correct and what can I do to overcome that 
problem?

Mike
-- 
www.soft-gems.net

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/emscripten-discuss/3E0EEA6F-D458-4771-8443-FD4E242808D4%40googlemail.com.


Re: Multiple inheritance

2023-08-14 Thread 'Mike Lischke' via emscripten-discuss
One possible workaround is to use the derived class in the bindings, where 
one of its base classes is required. That even works without changing the 
underlying C++ library code. In my case I changed:

class_>("CommonTokenStream")
.constructor()
.constructor();

to:

class_>("CommonTokenStream")
.constructor()
.constructor();

That limits the acceptable token source to lexers only, but in my case this 
is acceptable. Any other suggestion is still welcome!

On Monday, August 14, 2023 at 11:16:29 AM UTC+2 Mike Lischke wrote:

Hi all,

C++ multiple inheritance is not discussed in the documentation and there 
are only very old issues in the emscripten issue tracker. From what I read 
so far is that multiple inheritance is not supported in embind because JS 
does not support that. That's not false, but MI is used so often in C++ 
there must be a workaround (and I'm looking for one).

In my case I have `class Lexer : public Recognizer, public TokenSource {}`. 
In some places I need that lexer as a recognizer and in some I need it as 
token source. My bindings are like this (simplified):

class_>("Lexer$Internal") 
.property("mode", ::mode);

class_>("Lexer")
.constructor()
.allow_subclass("LexerWrapper", constructor());

Since I cannot specify both classes as base in the bindings call, I started 
with `base` which works fine. However, when I try to use the 
lexer class in a place where a token source is required, I get the error:

BindingError: Expected null or instance of TokenSource, got an instance of 
Recognizer at throwBindingError (file:...)

Side note: that approach to use `Lexer$Internal` and `LexerHelper` comes 
from the fact that `Lexer` is an abstract class, but I need to bind its 
constructor to allow calling that from JS where I use the Lexer to derive a 
JS class from. So, I created the (non-abstract) `LexerHelper` class and 
pretend it's the actual lexer class.

IIUC the error is bogus, because the checked class indeed derives from both 
base classes, only JS doesn't know that. What can I do to make this 
scenario work?

I experimented with leaving out the `Lexer` binding entirely (to avoid the 
MI dilemma), but that only caused the generated JS class to be not 
extendable.

Mike
-- 
www.soft-gems.net 

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/emscripten-discuss/819aacbf-ea39-46c6-bf8c-a4989cbc3760n%40googlegroups.com.


Multiple inheritance

2023-08-14 Thread 'Mike Lischke' via emscripten-discuss
Hi all,

C++ multiple inheritance is not discussed in the documentation and there are 
only very old issues in the emscripten issue tracker. From what I read so far 
is that multiple inheritance is not supported in embind because JS does not 
support that. That's not false, but MI is used so often in C++ there must be a 
workaround (and I'm looking for one).

In my case I have `class Lexer : public Recognizer, public TokenSource {}`. In 
some places I need that lexer as a recognizer and in some I need it as token 
source. My bindings are like this (simplified):

  class_>("Lexer$Internal")
.property("mode", ::mode);

  class_>("Lexer")
.constructor()
.allow_subclass("LexerWrapper", constructor());

Since I cannot specify both classes as base in the bindings call, I started 
with `base` which works fine. However, when I try to use the lexer 
class in a place where a token source is required, I get the error:

BindingError: Expected null or instance of TokenSource, got an instance of 
Recognizer
at throwBindingError (file:... <>)

Side note: that approach to use `Lexer$Internal` and `LexerHelper` comes from 
the fact that `Lexer` is an abstract class, but I need to bind its constructor 
to allow calling that from JS where I use the Lexer to derive a JS class from. 
So, I created the (non-abstract) `LexerHelper` class and pretend it's the 
actual lexer class.

IIUC the error is bogus, because the checked class indeed derives from both 
base classes, only JS doesn't know that. What can I do to make this scenario 
work?

I experimented with leaving out the `Lexer` binding entirely (to avoid the MI 
dilemma), but that only caused the generated JS class to be not extendable.

Mike
-- 
www.soft-gems.net

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/emscripten-discuss/A592CE2D-9873-4DB2-B771-CF095B47C1B6%40googlemail.com.


Re: Strategies to debug memory alignment issues

2023-08-12 Thread 'Mike Lischke' via emscripten-discuss
>>> 
>>> Is there some way you could make/share a minimal repro case?
>> 
>> I can try, but what I'd really need is a way to debug the C++ code. 
>> Otherwise it becomes a pretty frustrating trial and error experience, which 
>> costs a lot of time.
> 
> If you need real debugging, have you tried the chrome DWARF debugger 
> extension: https://developer.chrome.com/blog/wasm-debugging-2020/?   As far 
> as I know that is the only way to get a real debugging experience with 
> webassembly on the web today.   
>  

This is probably one of my next steps, though this is really a Node.js, not a 
web app, which means I have to strip out the Node.js stuff for debugging. Weird 
that there's no wasm debugger for VS Code yet. There are a number of wasm 
extensions, but they all more or less provide wasm syntax highlighting, nothing 
else. Maybe at some later time...

Mike
-- 
www.soft-gems.net

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/emscripten-discuss/F6AD3DF6-DB0D-44BB-8DE4-4FDCB8B2A8B1%40googlemail.com.


Re: Strategies to debug memory alignment issues

2023-08-11 Thread 'Mike Lischke' via emscripten-discuss
> 
> To me this looks like a heap smash.  Try enabling the address sanitizer.

I finally was able to enable ASAN. With the help of Sam Clegg I found why I got 
that "too many locals" error and once I fixed that I got a much better error 
report (use-after-free), with which I can continue to isolate the problem.

In case someone is interested: don't make your EMSCRIPTEN_BINDINGS call too 
large. I had bound 53 classes in a single call, some with a large list of 
members. Once I split the single call up into multiple ones, things started to 
work much better.

Thanks,

Mike
-- 
www.soft-gems.net

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/emscripten-discuss/7D97DBE8-1AD6-4180-9FBC-F2B228F9AE88%40googlemail.com.


Re: howto disable stack trace for console output of fprintf

2023-08-11 Thread 'Mike Lischke' via emscripten-discuss
> 
> I sometimes just want to print trace output from the C/C++ side and I do not 
> care about the stack trace info in that scenario. I already do know exactly 
> where the messages come from and the stack unnecessarily bloats the output by 
> 1-2 orders of magnitude - sometimes slowing the browser to a crawl due to the 
> amount of data, and unnecessarily complicating the actual use of the log 
> data..
> 
> How can EMSCRIPTEN's default impl of always including the stack info be 
> overridden to just print my plain fprint messages?

Instead of printf use std::cout << "your message" << yourObject << std::endl, 
if you are in C++. That only prints that message, nothing else (and does good 
formatting). I use that currently for debugging.

Mike
-- 
www.soft-gems.net

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/emscripten-discuss/A4EBC6FD-6F59-40BA-96C4-4799BC92B16C%40googlemail.com.


Re: Strategies to debug memory alignment issues

2023-08-11 Thread 'Mike Lischke' via emscripten-discuss
> 
> To me this looks like a heap smash. Try enabling the address sanitizer.

I tried, but that lead to this issue: 
https://github.com/emscripten-core/emscripten/issues/19346.

> On Wed, Aug 9, 2023 at 7:13 AM 'Mike Lischke' via emscripten-discuss 
>  <mailto:emscripten-discuss@googlegroups.com>> wrote:
>>> Hi all,
>>> 
>>> I have a memory alignment problem in a library, which I want to use via 
>>> wasm. To get more information I enabled USAN which reported the error, but 
>>> it makes no sense to me, because the error is within the STL, not my code. 
>>> The class I use is std::unordered_set<> with a custom hasher and a custom 
>>> comparer. The pointer given to the `insert` method (the error happens 
>>> already on first insertion) is aligned, I triple checked that. Here's the 
>>> full stack trace:
>>> 
>>> This is the pointer that should be inserted in the set:
>>> 
>>> proposed: 0x3bebe8
>>> 
>>> /opt/homebrew/Cellar/emscripten/3.1.43/libexec/cache/sysroot/include/c++/v1/__memory/unique_ptr.h:469:12:
>>>  runtime error: reference binding to misaligned address 0x3307474f for type 
>>> 'std::__hash_node_base *> 
>>> *', which requires 4 byte alignment
>>> 0x3307474f: note: pointer points here
>>> RuntimeError: memory access out of bounds
>>> at __ubsan::Diag::~Diag() 
>>> (wasm://wasm/0a18e74a:wasm-function[23303]:0xa1fae2)
>>> at handleTypeMismatchImpl(__ubsan::TypeMismatchData*, unsigned long, 
>>> __ubsan::ReportOptions) (wasm://wasm/0a18e74a:wasm-function[23315]:0xa20b40)
>>> at __ubsan_handle_type_mismatch_v1 
>>> (wasm://wasm/0a18e74a:wasm-function[23314]:0xa20695)
>>> at 
>>> std::__2::unique_ptr>>  void*>*>* [], 
>>> std::__2::__bucket_list_deallocator>>  void*>*>*>>>::operator[][abi:v160004](unsigned long) const 
>>> (wasm://wasm/0a18e74a:wasm-function[16520]:0x6dde0a)
>>> at 
>>> std::__2::pair>>  void*>*>, bool> std::__2::__hash_table>> antlr4::dfa::DFA::DFAStateHasher, antlr4::dfa::DFA::DFAStateComparer, 
>>> std::__2::allocator>::__emplace_unique_key_args>>  antlr4::dfa::DFAState* const&>(antlr4::dfa::DFAState* const&, 
>>> antlr4::dfa::DFAState* const&) 
>>> (wasm://wasm/0a18e74a:wasm-function[16515]:0x6dbbfb)
>>> at std::__2::__hash_table>> antlr4::dfa::DFA::DFAStateHasher, antlr4::dfa::DFA::DFAStateComparer, 
>>> std::__2::allocator>::__insert_unique[abi:v160004](antlr4::dfa::DFAState*
>>>  const&) (wasm://wasm/0a18e74a:wasm-function[16387]:0x6cb146)
>>> at std::__2::unordered_set>> antlr4::dfa::DFA::DFAStateHasher, antlr4::dfa::DFA::DFAStateComparer, 
>>> std::__2::allocator>::insert[abi:v160004](antlr4::dfa::DFAState*
>>>  const&) (wasm://wasm/0a18e74a:wasm-function[16382]:0x6ca8f2)
>>> at 
>>> antlr4::atn::LexerATNSimulator::addDFAState(antlr4::atn::ATNConfigSet*, 
>>> bool) (wasm://wasm/0a18e74a:wasm-function[16379]:0x6c9deb)
>>> at antlr4::atn::LexerATNSimulator::matchATN(antlr4::CharStream*) 
>>> (wasm://wasm/0a18e74a:wasm-function[16306]:0x6a4858)
>>> at antlr4::atn::LexerATNSimulator::match(antlr4::CharStream*, unsigned 
>>> long) (wasm://wasm/0a18e74a:wasm-function[16291]:0x6a095c)


Thanks,

Mike
-- 
www.soft-gems.net

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/emscripten-discuss/87A5087F-9A20-4462-9541-3E6358C3C141%40googlemail.com.


Re: Strategies to debug memory alignment issues

2023-08-11 Thread 'Mike Lischke' via emscripten-discuss
> 
> How did the issue present itself before you enabled UBSAN?   (Are you sure 
> its the same issue?)

It's pretty much the same:

RuntimeError: memory access out of bounds
at 
std::__2::pair*>, bool> std::__2::__hash_table>::__emplace_unique_key_args(antlr4::dfa::DFAState* const&, 
antlr4::dfa::DFAState* const&) 
(wasm://wasm/06ddd9e2:wasm-function[16499]:0x222e01)
at std::__2::__hash_table>::__insert_unique[abi:v160004](antlr4::dfa::DFAState*
 const&) (wasm://wasm/06ddd9e2:wasm-function[16371]:0x21f157)
at std::__2::unordered_set>::insert[abi:v160004](antlr4::dfa::DFAState*
 const&) (wasm://wasm/06ddd9e2:wasm-function[16366]:0x21ef8f)
at antlr4::atn::LexerATNSimulator::addDFAState(antlr4::atn::ATNConfigSet*, 
bool) (wasm://wasm/06ddd9e2:wasm-function[16363]:0x21ec90)
at antlr4::atn::LexerATNSimulator::matchATN(antlr4::CharStream*) 
(wasm://wasm/06ddd9e2:wasm-function[16290]:0x218e8a)
at antlr4::atn::LexerATNSimulator::match(antlr4::CharStream*, unsigned 
long) (wasm://wasm/06ddd9e2:wasm-function[16275]:0x2183e1)
at antlr4::Lexer::nextToken() 
(wasm://wasm/06ddd9e2:wasm-function[12053]:0x17b1bf)
at embind_init_main()::$_6::operator()(LexerHelper&) const 
(wasm://wasm/06ddd9e2:wasm-function[3619]:0xa43d3)
at embind_init_main()::$_6::__invoke(LexerHelper&) 
(wasm://wasm/06ddd9e2:wasm-function[3618]:0xa4362)
at 
emscripten::internal::FunctionInvoker> (*)(LexerHelper&), 
std::__2::unique_ptr>, 
LexerHelper&>::invoke(std::__2::unique_ptr> (**)(LexerHelper&), LexerHelper*) 
(wasm://wasm/06ddd9e2:wasm-function[3611]:0xa4111)

> 
> Is there some way you could make/share a minimal repro case?

I can try, but what I'd really need is a way to debug the C++ code. Otherwise 
it becomes a pretty frustrating trial and error experience, which costs a lot 
of time.

> 
> cheers,
> sam

Thanks for trying to help Sam!

Mike
-- 
www.soft-gems.net

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/emscripten-discuss/5C24A416-9A4C-48BA-9871-4E10B8508A4E%40googlemail.com.


Strategies to debug memory alignment issues

2023-08-09 Thread 'Mike Lischke' via emscripten-discuss
Hi all,

I have a memory alignment problem in a library, which I want to use via wasm. 
To get more information I enabled USAN which reported the error, but it makes 
no sense to me, because the error is within the STL, not my code. The class I 
use is std::unordered_set<> with a custom hasher and a custom comparer. The 
pointer given to the `insert` method (the error happens already on first 
insertion) is aligned, I triple checked that. Here's the full stack trace:

This is the pointer that should be inserted in the set:

proposed: 0x3bebe8

/opt/homebrew/Cellar/emscripten/3.1.43/libexec/cache/sysroot/include/c++/v1/__memory/unique_ptr.h:469:12:
 runtime error: reference binding to misaligned address 0x3307474f for type 
'std::__hash_node_base *> *', 
which requires 4 byte alignment
0x3307474f: note: pointer points here
RuntimeError: memory access out of bounds
at __ubsan::Diag::~Diag() 
(wasm://wasm/0a18e74a:wasm-function[23303]:0xa1fae2)
at handleTypeMismatchImpl(__ubsan::TypeMismatchData*, unsigned long, 
__ubsan::ReportOptions) (wasm://wasm/0a18e74a:wasm-function[23315]:0xa20b40)
at __ubsan_handle_type_mismatch_v1 
(wasm://wasm/0a18e74a:wasm-function[23314]:0xa20695)
at 
std::__2::unique_ptr*>* [], 
std::__2::__bucket_list_deallocator*>*>>>::operator[][abi:v160004](unsigned long) const 
(wasm://wasm/0a18e74a:wasm-function[16520]:0x6dde0a)
at 
std::__2::pair*>, bool> std::__2::__hash_table>::__emplace_unique_key_args(antlr4::dfa::DFAState* const&, 
antlr4::dfa::DFAState* const&) 
(wasm://wasm/0a18e74a:wasm-function[16515]:0x6dbbfb)
at std::__2::__hash_table>::__insert_unique[abi:v160004](antlr4::dfa::DFAState*
 const&) (wasm://wasm/0a18e74a:wasm-function[16387]:0x6cb146)
at std::__2::unordered_set>::insert[abi:v160004](antlr4::dfa::DFAState*
 const&) (wasm://wasm/0a18e74a:wasm-function[16382]:0x6ca8f2)
at antlr4::atn::LexerATNSimulator::addDFAState(antlr4::atn::ATNConfigSet*, 
bool) (wasm://wasm/0a18e74a:wasm-function[16379]:0x6c9deb)
at antlr4::atn::LexerATNSimulator::matchATN(antlr4::CharStream*) 
(wasm://wasm/0a18e74a:wasm-function[16306]:0x6a4858)
at antlr4::atn::LexerATNSimulator::match(antlr4::CharStream*, unsigned 
long) (wasm://wasm/0a18e74a:wasm-function[16291]:0x6a095c)

To me it looks like the set tries to insert a random memory address. I added 
console logging in the entire path, including the hasher, to see what's going 
on (feeling like debugging in the 90s :-( ) and everything looks good. The hash 
is created and looks valid, but after that the crash happens. So what else 
could I do to debug further?

For completeness, this is how the set member is defined:

std::unordered_set states; // 
States are owned by this class.

No unique pointers involved here, so this must be something internal to the set.

Mike
-- 
www.soft-gems.net

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/emscripten-discuss/ECB3B320-77B3-4B6E-A51C-8199FC547AAB%40googlemail.com.


Re: A ctor which receives const char*

2023-08-07 Thread 'Mike Lischke' via emscripten-discuss
> Here is the full compiling cpp code:
> 
> #include 
> #include 
> #include 
> 
> class Foo
> {
>   public:
>   Foo(const char* a, const char* b, const char* c)
>   {
>  m_a = std::string(a);
>  m_b = std::string(b);
>  m_c = std::string(c);
>   }
> 
>   private:
>   std::string m_a;
>   std::string m_b;
>   std::string m_c;
> };
> 
> 
> EMSCRIPTEN_BINDINGS(FooTest)
> {
> emscripten::class_("Foo").
> constructor();
> }
> 
> ב-יום שני, 7 באוגוסט 2023 בשעה 08:03:35 UTC+3, Shlomi Fish כתב/ה:

Is this supposed to be called from JS? If so, how can you provide char pointers 
for the constructor, given that you only have JS strings?

Instead use std::string for the constructor. If you cannot change that write a 
helper class which takes strings and passes the data() pointer along to the 
inherited c-tor. Alternatively, you can write a constructor factory method, 
known as external constructor 
(https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#external-constructors).

Mike
-- 
www.soft-gems.net

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/emscripten-discuss/9AE2E2FB-6CFA-47A4-8166-2E615D5ED66E%40googlemail.com.


Re: embind- pass class to class

2023-08-07 Thread 'Mike Lischke' via emscripten-discuss
Hi Ronny,

> Is it possible using the current EMBIND to pass one CPP class to another?
> For example:
> Here I tried constructing class Bar in the same binding declaration as Foo, 
> and construct a Bar using Foo.
> Is it possible at all, and if yes how?
> Thanks
> Ronny
> 
> 
> EMSCRIPTEN_BINDINGS(Test) {
> emscripten::class_("Foo").
> constructor().
> emscripten::class_("Bar").
> constructor();
> }

Sure is it possible, if you pass in the class as raw or smart pointer:

EMSCRIPTEN_BINDINGS(Test) {
emscripten::class_("Foo").
constructor();

emscripten::class_("Bar").
constructor();
}

Watch out to terminate a class declaration properly. If I'm not wrong then you 
cannot bind a new class to the result of a constructor call of a previous class.

Mike
-- 
www.soft-gems.net

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/emscripten-discuss/2251F5AB-EA87-49B8-A0A2-DCC71A43B008%40googlemail.com.


Binding a method which returns std::string_view

2023-07-08 Thread 'Mike Lischke' via emscripten-discuss
Hi al,

In a class I have a method which returns a std::string_view, which gives me an 
unbound error when binding the method and using that directly. So I'm trying to 
implicitly convert the string view:

  class_("Vocabulary")
.constructor<>()
.function("getLiteralName",
  [](dfa::Vocabulary , size_t tokenType) {
std::string s(self.getLiteralName(tokenType));
return s;
  });

Unfortunately, this doesn't compile because of a template error:

/opt/homebrew/Cellar/emscripten/3.1.41/libexec/cache/sysroot/include/emscripten/bind.h:1709:9:
 error: implicit instantiation of undefined template 
'emscripten::internal::RegisterClassMethod<(lambda at 
wasm/runtime-dfa.h:52:15)>'
 1709 | invoker::template invoke(methodName, 
callable);
  | ^
wasm/runtime-dfa.h:51:6: note: in instantiation of function template 
specialization 
'emscripten::class_::function' requested here
   51 | .function("getLiteralName",
  |  ^
/opt/homebrew/Cellar/emscripten/3.1.41/libexec/cache/sysroot/include/emscripten/bind.h:1413:8:
 note: template is declared here
 1413 | struct RegisterClassMethod;

The method declaration is:

std::string_view getLiteralName(size_t tokenType) const;

What's the correct code to use here?

Thanks,

Mike

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/emscripten-discuss/20B18F67-FC23-42F7-82E6-EA6B794F02A7%40googlemail.com.