Clearscript V8 engine hang while debugging

Jan 13, 2016 at 10:04 AM
Hi,

I am running Clearscript v8 script engine in debug mode to control script execution(Play,Pause,Stop). Clearscript V8 engine executing all scripts perfectly. I we put execution in a loop, after few script execution v8 will not write any response to newtork stream, it just hang.
//Clearscript  V8 script engine.
            var debuggingPort =2015;

            m_scriptEngine = new V8ScriptEngine(V8ScriptEngineFlags.DisableGlobalMembers | V8ScriptEngineFlags.EnableDebugging, debuggingPort)
            {
                AllowReflection = false,
            };
            Uri portUri = new Uri("tcp://127.0.0.1:"+debuggingPort);
            m_tcpClient = new TcpClient(portUri.Host, portUri.Port);
Send request to V8 Debug engine
      private Task<Response> SendRequestAsync(Request request, CancellationToken cancellationToken = new CancellationToken()) 
        {
            cancellationToken.ThrowIfCancellationRequested();

            if (request.Sequence.HasValue == false)
                request.Sequence = m_currentSequence++;
            else
                m_currentSequence = request.Sequence.Value + 1;

             var requestResetEvent = new ManualResetEvent(false);
             _requestWaitHandles.AddOrUpdate(request.Sequence.Value, requestResetEvent, (id, r) => requestResetEvent);

             var serializedRequest = JsonConvert.SerializeObject(request);  
    //ex:- serializedRequest ={"seq":1,"type":"request","command":"setbreakpoint","arguments":{"type":"script","target":"1fa9ab33-fea8-41f5-91a4-d891e361a52f_IdeFfeVoLb.js [temp]","line":0}}

             return Task.Run(() => {

                 SendMessage(serializedRequest);

                 requestResetEvent.WaitOne();

                 Response response = null;
                 _responses.TryRemove(request.Sequence.Value, out response);

                 _requestWaitHandles.TryRemove(request.Sequence.Value, out requestResetEvent);

                 return response;
             });             
        }

        private async void SendMessage(string message) 
        {
            try
            {
               
                TcpClient networkClient;
                lock (m_networkClientLock)
                {
                    networkClient = m_tcpClient;
                }

                var networkStream = m_tcpClient.GetStream();

                var streamWriter = new StreamWriter(networkStream);
                
                int byteCount = Encoding.UTF8.GetByteCount(message);
                string request = string.Format("Content-Length: {0}{1}{1}{2}", byteCount, Environment.NewLine, message);

                if(Connected)
                {
                    await streamWriter.WriteAsync(request).ConfigureAwait(false);                    
                    await streamWriter.FlushAsync().ConfigureAwait(false);
                                       
                    WriteToLogFile("Written to stream. Message:" + request);                    
                }                
            }
            catch (Exception e)
            {
                WriteToLogFile("Exception writing to stream. Err Mesg:" + e.Message + Environment.NewLine);                    
                Debug.Write("Exception writing to stream. Err Mesg:" + e.Message+Environment.NewLine);
            }
Reading response from engine using while loop.
var networkStream=networkClient.GetStream();
                //networkStream.ReadTimeout = 2000;

                using (var streamReader = new StreamReader(networkStream, Encoding.Default))                              
                {                    
                   while (Connected) 
                   {
                       //if (networkStream.DataAvailable)
                       {
                           try
                           {
                               WriteToLogFile("Before Response: ");

                               var result = await streamReader.ReadLineAsync().ConfigureAwait(false);
                               //var result = streamReader.ReadLine();

                               WriteToLogFile("Response from engine. Response: " + result);

                               if (result == null)
                               {
                                   continue;
                               }

                               // Check whether result is content length header
                               var match = m_contentLength.Match(result);

                               if (!match.Success)
                               {
                                   //DebugWriteLine(string.Format("Debugger info: {0}", result));
                                   continue;
                               }

                               await streamReader.ReadLineAsync().ConfigureAwait(false);

                               // Retrieve content length
                               var length = int.Parse(match.Groups[1].Value);
                               if (length == 0)
                               {
                                   continue;
                               }

                               // Read content
                               string message = await streamReader.ReadLineBlockAsync(length).ConfigureAwait(false);

                               WriteToLogFile("Response from engine. Response: " + message);

                               HandleOutput(message);
                           }
                           catch (Exception exx)
                           {
                               WriteToLogFile("Exception reading from stream. Err Mesg:" + exx.Message + Environment.NewLine);
                           }
                       }
                    }
                }
Script hanging at line
var result = await streamReader.ReadLineAsync().ConfigureAwait(false);
No response from Clearscript V8 engine. step in request sent to engine on breakpoint event. Is there any other technique to control script execution.

Thanks and Regards
Praveen Kumar
Coordinator
Jan 13, 2016 at 2:57 PM
Hi Praveen,

It's difficult for us to diagnose this kind of issue armed only with partial code from your application and without detailed information about its overall design, its process/thread architecture, the scripts being executed, etc.

One suggestion would be to try to reproduce the issue using Eclipse instead of your custom debugger (see the ClearScript ReadMe for more information). That might help you determine whether the problem is within ClearScript. Would that be possible?

Also, please make sure you're using ClearScript 5.4.3 or later.

Thanks!
Jan 14, 2016 at 8:34 AM
Hi,

We are using ClearScript.V8 5.4.4 (nuget). We used signalr project (https://github.com/Oceanswave/V8SignalRDebugging) to create custom debugger posted in discussion (http://clearscript.codeplex.com/discussions/560977). Clearscript V8 engine will alwalys run scripts in debug mode, on break point event we decide continue script or not.

Thanks
Praveen Kumar
Coordinator
Jan 14, 2016 at 3:46 PM
Thanks Praveen.

Eclipse is our test environment for ClearScript's V8 debug server, and currently we're not aware of any issues. Please let us know if you can reproduce your issue in Eclipse. Or, if you can provide a complete sample that reproduces it, we'll be happy to take a look.

Thanks!
Jan 18, 2016 at 7:33 AM
Edited Jan 18, 2016 at 8:41 AM
Hi,

I have included test project in github((https://github.com/NKumarPraveen/ClearScriptV8Debugger)). issue with stream reading from engine.
                if(Connected)
                {
                    await streamWriter.WriteAsync(request).ConfigureAwait(false);                    
                    await streamWriter.FlushAsync().ConfigureAwait(false);
                                       
                    WriteToLogFile("Written to stream. Message:" + request);                    
                }   
and
            {
                TcpClient networkClient;
                
                lock (m_networkClientLock)
                {
                    networkClient = m_tcpClient;
                }

                var networkStream=networkClient.GetStream();
                //networkStream.ReadTimeout = 2000;

                using (var streamReader = new StreamReader(networkStream, Encoding.Default))                              
                {                    
                   while (Connected) 
                   {
                       //if (networkStream.DataAvailable)
                       {
                           try
                           {
                               WriteToLogFile("Before Response: ");

                               var result = await streamReader.ReadLineAsync().ConfigureAwait(false);
                               //var result = streamReader.ReadLine();

                               WriteToLogFile("Response from engine. Response: " + result);

                               if (result == null)
                               {
                                   continue;
                               }

                               // Check whether result is content length header
                               var match = m_contentLength.Match(result);

                               if (!match.Success)
                               {
                                   //DebugWriteLine(string.Format("Debugger info: {0}", result));
                                   continue;
                               }

                               await streamReader.ReadLineAsync().ConfigureAwait(false);

                               // Retrieve content length
                               var length = int.Parse(match.Groups[1].Value);
                               if (length == 0)
                               {
                                   continue;
                               }

                               // Read content
                               string message = await streamReader.ReadLineBlockAsync(length).ConfigureAwait(false);

                               WriteToLogFile("Response from engine. Response: " + message);

                               HandleOutput(message);
                           }
                           catch (Exception exx)
                           {
                               WriteToLogFile("Exception reading from stream. Err Mesg:" + exx.Message + Environment.NewLine);
                           }
                       }
                    }
                }
            }
Also logging to text file in temp folder(V8Enginelog.log).

Thanks and Regards
Praveen
Coordinator
Jan 18, 2016 at 6:21 PM
Edited Jan 18, 2016 at 6:29 PM
Hi Praveen,

Thanks for posting your test project, but we're not seeing any issues. The test program appears to run to completion every time, even with several loops running simultaneously.

Image

Any thoughts?
Jan 19, 2016 at 5:29 AM
Hi,

This issue cannot reproducible all the time. I have executed on different windows OS 32 & 64 bit, can be producible on following.

Windows 7 64 bit => Recreated issue
Windows 8 64 bit => Recreated issue

Windows 7 32 bit => Working
Windows 8 32 bit => Working
Windows 8.1 32 bit => Working
Windows 8.1 64 bit => Working

This frequently recreated on Windows 7 64 bit & Windows 8 64 bit.

Thanks
Praveen.
Jan 25, 2016 at 7:29 AM
Hi,

Any other debugger technique available in clearscript v8 engine other than remote debugging.

Thanks and Regards
Praveen Kumar N
Coordinator
Jan 25, 2016 at 12:24 PM
Hi Praveen,

Using your test program, we've reproduced the issue on Windows 7 x64, but it's very intermittent, so we don't have a diagnosis at this time.

As for alternate techniques, what are your requirements? Are you only interested in pausing and resuming script execution, or do you need to do more than that?

Thanks!
Jan 25, 2016 at 2:35 PM
Edited Jan 26, 2016 at 3:42 PM
Hi,

Thank you, yes it is intermittent we have already implemented this debugger feature in our application. we are able to control execution line by line using pause resume feature, also scripts may be long running or automation script. it would be helpful if we have any alternative for this.
Is it possible apply interception mechanism on native class objects or any callback on method calls.

Thank you
Praveen
Coordinator
Jan 26, 2016 at 7:36 PM
Hi Praveen,

What are your requirements? Does it have to be line-by-line pause/resume? Do you only need execution control, or do you need other debugger capabilities (e.g., access to local variables, etc.)?

Thanks!
Jan 27, 2016 at 3:06 AM
Hi,
  1. Requirements
    Script execution control pause/resume(using this able show progress of script execution). we are using this feature to control execution not for debugging.
  2. Does it have to be line-by-line pause/resume?
    Yes.
  3. Do you only need execution control?
    Yes.
  4. Do you need other debugger capabilities?.
    Yes, we are able to access local variable and its values using debugger protocol command and using Script property of engine.
Thank you
Praveen
Coordinator
Jan 28, 2016 at 1:23 PM
Hi again,

The debugger protocol is the only way to step through script code line-by-line. There may be other ways to do pause/resume, but it wouldn't be based on source line breakpoints, so you probably couldn't use it to show progress.

Cheers!
Nov 24, 2016 at 5:13 PM
Hi

I've implemented a similar approach as Praveen, but encountered the same issue :(

Nevertheless, I would be more than happy if I just could pause/resume, so if there is any other option to achieve a simple pause/resume functionality, I would appreciate if you could share this.

Thanks
Marco
Coordinator
Nov 26, 2016 at 1:55 PM
Hi Marco,

One possibility might be to use ScriptEngine.ContinuationCallback. Your callback might look something like this:
engine.ContinuationCallback = () => {
    while (ScriptIsPaused()) {
        Thread.Sleep(500);
    }
    return true;
};
Note that the engine only invokes the callback approximately once every two seconds, so this technique doesn't give you very precise pause/resume control.

Good luck!
Dec 9, 2016 at 5:42 PM
Hi,

Thanks for the hint.

Best,
Marco