Hi again,

I figured that the `chome-devtools://` part doesn't work in Chromium.  
Using `devtools://` instead works. However, I get a segmentation violation. 

Here is the code I wrote to connect the V8 inspector:

    struct ServerChannel : v8_inspector::V8Inspector::Channel
    {
        private:
        sockpp::tcp_socket *socket_;

        public:
        ServerChannel() { }

        void set_socket(sockpp::tcp_socket *socket) { socket_ = socket; }

        private:
        void sendResponse(int, std::unique_ptr<v8_inspector::StringBuffer> 
message) override {
            auto v8_sv = message->string();
            socket_->write_n(v8_sv.characters8(), v8_sv.length());
        }

        void sendNotification(std::unique_ptr<v8_inspector::StringBuffer> 
message) override {
            auto v8_sv = message->string();
            socket_->write_n(v8_sv.characters8(), v8_sv.length());
        }

        void flushProtocolNotifications() override { }
    };

    struct MyV8InspectorClient : v8_inspector::V8InspectorClient
    {
        private:
        sockpp::tcp_acceptor acceptor_;
        std::unique_ptr<ServerChannel> channel_;
        std::unique_ptr<v8_inspector::V8Inspector> inspector_;
        std::unique_ptr<v8_inspector::V8InspectorSession> session_;
        int16_t port_;

        public:
        MyV8InspectorClient(int16_t port, v8::Isolate *isolate)
            : acceptor_(port)
            , port_(port)
        {
            if (not acceptor_)
                throw std::runtime_error("failed to initalize TCP server");

            channel_ = std::make_unique<ServerChannel>();
            inspector_ = v8_inspector::V8Inspector::create(isolate, this);

            std::string state("mutable");
            v8_inspector::StringView sv(reinterpret_cast<const 
uint8_t*>(state.c_str()), state.length());
            session_ = inspector_->connect(
                /* contextGroupId= */ 1,
                /* channel=        */ channel_.get(),
                /* state=          */ sv
            );
        }

        MyV8InspectorClient(const MyV8InspectorClient&) = delete;
        MyV8InspectorClient(MyV8InspectorClient&&) = default;

        ~MyV8InspectorClient() {
            session_.reset();
            inspector_.reset();
            channel_.reset();
        }

        void onMessage(std::string_view sv) {
            v8_inspector::StringView msg(reinterpret_cast<const 
uint8_t*>(sv.data()), sv.length());
            session_->dispatchProtocolMessage(msg);
        }

        void launch() {
            std::cout << "WebSocket based Inspector Agent started.\n"
                      << "Open the following link in your Chrome/Chromium 
browser:\n\n\t"
                      << 
"devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:"
 
<<  port_
                      << '\n' << std::endl;

            auto socket = 
std::make_unique<sockpp::tcp_socket>(acceptor_.accept());
            if (not *socket)
                throw std::runtime_error("failed to establish connection to 
TCP client");
            channel_->set_socket(socket.get());

            auto thread = 
std::thread([this](std::unique_ptr<sockpp::tcp_socket> socket) {
                uint8_t buf[512];
                std::vector<uint8_t> msg;
                msg.reserve(512);
                std::size_t n;

                for (;;) {
                    std::cerr << "receiving bytes..." << std::endl;
                    while ((n = socket->read_n(buf, ARR_SIZE(buf))) > 0)
                        msg.insert(msg.end(), buf, buf + n); // append 
recently read bytes to msg
                    if (not msg.empty()) {
                        std::cerr << "the received message is " << 
msg.size() << " bytes" << std::endl;
                        std::string_view 
sv(reinterpret_cast<char*>(&msg[0]), msg.size());
                        this->onMessage(sv);
                        msg.clear();
                    }
                    std::this_thread::yield();
                }
            },
            std::move(socket));
            thread.detach();
        }
    };

It's mostly taken from your example and condensed into a single class.  
Instead of boost, I use sockpp for socket programming.i

After creating a `v8::Isolate`, I do the following:

        inspector_ = std::make_unique<MyV8InspectorClient>(cdt_port, 
isolate_);
        inspector_->launch();

However, when connecting to the inspector it says "WebSocket disconnected" 
and the application crashes with a segmentation violation:

    AddressSanitizer:DEADLYSIGNAL
    =================================================================
    ==13072==ERROR: AddressSanitizer: SEGV on unknown address 
0x1d580000a838 (pc 0x561c8173e6b4 bp 0x7fff75fa6430 sp 0x7fff75fa6430 T0)
    ==13072==The signal is caused by a READ memory access.
        #0 0x561c8173e6b4 in v8::Isolate::GetHeapProfiler() 
../../../../../third-party/v8/v8/src/execution/isolate.h:1059:48
        #1 0x561c82d3fd77 in 
v8_inspector::V8HeapProfilerAgentImpl::stopTrackingHeapObjectsInternal() 
../../../../../third-party/v8/v8/src/inspector/v8-heap-profiler-agent-impl.cc:316:14
        #2 0x561c82d3feb9 in 
v8_inspector::V8HeapProfilerAgentImpl::disable() 
../../../../../third-party/v8/v8/src/inspector/v8-heap-profiler-agent-impl.cc:204:3
        #3 0x561c8208f095 in 
v8_inspector::V8InspectorSessionImpl::~V8InspectorSessionImpl() 
../../../../../third-party/v8/v8/src/inspector/v8-inspector-session-impl.cc:151:24
        #4 0x561c8208f33d in 
v8_inspector::V8InspectorSessionImpl::~V8InspectorSessionImpl() 
../../../../../third-party/v8/v8/src/inspector/v8-inspector-session-impl.cc:147:51
        #5 0x561c80ec9eff in 
std::default_delete<v8_inspector::V8InspectorSession>::operator()(v8_inspector::V8InspectorSession*)
 
const 
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../include/c++/10.1.0/bits/unique_ptr.h:84:2
        #6 0x561c80ec9d3e in 
std::__uniq_ptr_impl<v8_inspector::V8InspectorSession, 
std::default_delete<v8_inspector::V8InspectorSession> 
>::reset(v8_inspector::V8InspectorSession*) 
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../include/c++/10.1.0/bits/unique_ptr.h:181:4
        #7 0x561c80eca183 in 
std::unique_ptr<v8_inspector::V8InspectorSession, 
std::default_delete<v8_inspector::V8InspectorSession> 
>::reset(v8_inspector::V8InspectorSession*) 
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../include/c++/10.1.0/bits/unique_ptr.h:455:7
        #8 0x561c80ec7193 in 
db::v8_helper::MyV8InspectorClient::~MyV8InspectorClient() 
/home/immanuel/Documents/Work/PhD/mutable/mutable/build/debug/../../src/backend/V8Platform.hpp:74:18
        #9 0x561c80ec723b in 
db::v8_helper::MyV8InspectorClient::~MyV8InspectorClient() 
/home/immanuel/Documents/Work/PhD/mutable/mutable/build/debug/../../src/backend/V8Platform.hpp:73:28
        #10 0x561c80eb361f in 
std::default_delete<db::v8_helper::MyV8InspectorClient>::operator()(db::v8_helper::MyV8InspectorClient*)
 
const 
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../include/c++/10.1.0/bits/unique_ptr.h:84:2
        #11 0x561c80eaede6 in 
std::unique_ptr<db::v8_helper::MyV8InspectorClient, 
std::default_delete<db::v8_helper::MyV8InspectorClient> >::~unique_ptr() 
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../include/c++/10.1.0/bits/unique_ptr.h:360:4
        #12 0x561c80ea6e97 in db::V8Platform::~V8Platform() 
/home/immanuel/Documents/Work/PhD/mutable/mutable/build/debug/../../src/backend/V8Platform.cpp:221:1
        #13 0x561c80ea6f2b in db::V8Platform::~V8Platform() 
/home/immanuel/Documents/Work/PhD/mutable/mutable/build/debug/../../src/backend/V8Platform.cpp:218:1
        #14 0x561c80e9ea3f in 
std::default_delete<db::WasmPlatform>::operator()(db::WasmPlatform*) const 
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../include/c++/10.1.0/bits/unique_ptr.h:84:2
        #15 0x561c80e9e8f6 in std::unique_ptr<db::WasmPlatform, 
std::default_delete<db::WasmPlatform> >::~unique_ptr() 
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../include/c++/10.1.0/bits/unique_ptr.h:360:4
        #16 0x561c80e8efbd in db::WasmBackend::~WasmBackend() 
/home/immanuel/Documents/Work/PhD/mutable/mutable/build/debug/../../src/backend/WebAssembly.hpp:110:8
        #17 0x561c80e8efeb in db::WasmBackend::~WasmBackend() 
/home/immanuel/Documents/Work/PhD/mutable/mutable/build/debug/../../src/backend/WebAssembly.hpp:110:8
        #18 0x561c80ccf1ff in 
std::default_delete<db::Backend>::operator()(db::Backend*) const 
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../include/c++/10.1.0/bits/unique_ptr.h:84:2
        #19 0x561c80ca8b16 in std::unique_ptr<db::Backend, 
std::default_delete<db::Backend> >::~unique_ptr() 
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../include/c++/10.1.0/bits/unique_ptr.h:360:4
        #20 0x561c80c86dd9 in process_stream(std::istream&, char const*, 
db::Diagnostic) 
/home/immanuel/Documents/Work/PhD/mutable/mutable/build/debug/../../src/shell.cpp:151:13
        #21 0x561c80c9a265 in main 
/home/immanuel/Documents/Work/PhD/mutable/mutable/build/debug/../../src/shell.cpp:675:13
        #22 0x7f6259a37001 in __libc_start_main (/usr/lib/libc.so.6+0x27001)
        #23 0x561c80ba722d in _start 
(/home/immanuel/Documents/Work/PhD/mutable/mutable/build/debug/bin/shell+0x117222d)

    AddressSanitizer can not provide additional info.
    SUMMARY: AddressSanitizer: SEGV 
../../../../../third-party/v8/v8/src/execution/isolate.h:1059:48 in 
v8::Isolate::GetHeapProfiler()

Can you spot what's going wrong?  I did not override 
`V8InspectorClientImpl::runMessageLoopOnPause` like you did. Is this 
necessary?

Kind regards,
Immanuel
Elmi Ahmadov schrieb am Mittwoch, 19. August 2020 um 21:40:58 UTC+2:

> Dear Immanuel,
>
> You've got the right idea from my example code. You need a websocket to 
> create a communication channel between V8 Inspector and CDT.
> The URL to debug the code is usually as follows and it works for me.
>
> devtools:
> //devtools/bundled/inspector.html?experiments=true&v8only=true&ws=IP:WebSocketPort
>
> Without a minimal sample code it's difficult to say what you're missing. 
> You can also use Chrome DevTools Network Activity tab (you need to open 
> another Inspector console, see the screenshot), just filter *WS* to see 
> what happens between your server and CDT, which helped me a lot.
>  
>
> [image: Screenshot from 2020-08-19 21-37-48.png]
>
> There is another Chrome built-in feature that helped me is *Protocol 
> Monitor*, you can here how to enable it: 
> https://chromedevtools.github.io/devtools-protocol/
>
> On Wednesday, August 19, 2020 at 4:17:00 PM UTC+2, Immanuel Haffner wrote:
>>
>>
>> Dear Elmi,
>>
>> thank you for your reply. I had a long look at your example. To be 
>> honest, I find it a bit bloatet.
>>
>> Let me phrase in my own words what I have learned from your code:
>>
>> 1) I need a socket to receive messages from CDT and send responses back 
>> to CDT.
>> 2) I must implement `v8_inspector::V8Inspector::Channel` to have 
>> `sendResponse()` and `sendNotification()` send the respective message over 
>> the socket to CDT.
>> 3) I need an instance of `v8_inspector::V8InspectorClient`. I am not sure 
>> whether I must overwrite anything from this class in a subclass. I think 
>> the base class is actually fine...
>> 4) I must use `v8_inspector::V8Inspector::create()` to create an instance 
>> of `v8_inspector::V8Inspector`. I believe this is where all the inspector 
>> logic is implemented...
>> 5) Using the `V8Inspector` instance I create a 
>> `v8_inspector::V8InspectorSession` by calling `connect()`. Here I must pass 
>> a reference to an instance of my `v8_inspector::V8Inspector::Channel` 
>> subclass.
>> This was the basic setup. Now it's time to run the server loop.
>> 6) In a detached thread, read from the socket and pass the message on by 
>> invoking `dispatchProtocolMessage()` on my instance 
>> of `v8_inspector::V8InspectorSession`.
>>
>> When running my code, the TCP acceptor is set up and waiting for a 
>> client. I visit `localhost:<PORT>` with Chromium (the chrome-devtool:// 
>> links just won't work). Then my application executes the WebAssembly and 
>> the browser says the page isn't working (ERR_EMPTY_RESPONSE).
>>
>> What am I missing?
>> Elmi Ahmadov schrieb am Mittwoch, 19. August 2020 um 10:21:38 UTC+2:
>>
>>> Hi.
>>>
>>> I have an example project how to use V8 inspector API: 
>>> https://github.com/ahmadov/v8_inspector_example. Hope this would help.
>>>
>>> Best regards
>>>
>>> On Wednesday, August 19, 2020 at 10:11:00 AM UTC+2, Immanuel Haffner 
>>> wrote:
>>>>
>>>> Hi all,
>>>>
>>>> I followed this V8 documentation [1] to embed V8 into my application. 
>>>> The application compiles inputs to WebAssembly modules and executes them 
>>>> in 
>>>> embedded V8.  Now I would like to debug these WebAssembly modules.  
>>>> Searching online brought me to ChromeDevTools and the v8-inspector API.  I 
>>>> mostly followed this guide [2] to set up a `V8InspectorSession` and 
>>>> implemented the `V8Inspector::Channel` interface by creating a TCP server, 
>>>> waiting for a connection, and then in `sendResponse()` and 
>>>> `sendNotification()` I simply send the message over the TCP socket.
>>>>
>>>> To debug, I launch chromium and connect to localhost on the port where 
>>>> the TCP server was created. Sadly, this doesn't work. The `sendResponse()` 
>>>> and `sendNotification()` methods are never invoked.
>>>>
>>>> Can someone please point me to a tutorial or give me some guidance?
>>>>
>>>> Thanks,
>>>> Immanuel
>>>>
>>>> [1] https://v8.dev/docs/embed
>>>> [2] 
>>>> https://hyperandroid.com/2020/02/12/v8-inspector-from-an-embedder-standpoint/
>>>>
>>>

-- 
-- 
v8-users mailing list
v8-users@googlegroups.com
http://groups.google.com/group/v8-users
--- 
You received this message because you are subscribed to the Google Groups 
"v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/v8-users/922acb1e-625f-4d16-82b0-3d34a12e51c1n%40googlegroups.com.

Reply via email to