Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows support #5

Closed
db4 opened this issue Jun 21, 2016 · 33 comments
Closed

Windows support #5

db4 opened this issue Jun 21, 2016 · 33 comments

Comments

@db4
Copy link
Contributor

db4 commented Jun 21, 2016

What is the reason to use mkfifo for ocamldebug stdout/stderr redirection? You interact with ocamlmerlin without that (BTW it works well under Windows), why not to handle ocamldebug just the same way?

@hackwaly
Copy link
Owner

hackwaly commented Jun 21, 2016

Ocamldebug doesn't have a well-designed protocol. It's text based, and mainly face to user. If we don't use mkfifo, debuggee program's stdout and stderr will directly mixed into ocamldebug's stdout. We can't extract those out, because debuggee might output same message format as ocamldebug outputs.

Clarify: Ocamldebug's stdout/stderr is not redirected. Debuggee's stdout/stderr is redirected.

@hackwaly hackwaly reopened this Jun 21, 2016
@hackwaly
Copy link
Owner

Sorry for mis-pressed close button.

@db4
Copy link
Contributor Author

db4 commented Jun 21, 2016

I think you are just wrong here. ocamldebug is able to debug a remote process (set loadingmode manual), and so debug/debuggee can have different stderr/stdout. You launch ocamldebug, issue "set loadingmode manual", wait connection from the debuggee, then launch the debuggee. For a working example you can look into OCaIDE Eclipse plugin (https://github.com/nbros/OcaIDE/blob/master/Ocaml/src/ocaml/debugging/OcamlDebugger.java). BTW, remote debugging support is valuable thing by its own; I would love to see it implemented for vscode as well.

As for ocamldebug protocol, I would recommend to run it with -machine-readable command line option. This way you will have more predictable result that should be the same for different OCaml versions.

@hackwaly
Copy link
Owner

Thank you very much!

I'm going to improve debug support as you describe.

@hackwaly
Copy link
Owner

New version with remote debug support is published. Take a try!

@db4
Copy link
Contributor Author

db4 commented Jun 23, 2016

It doesn't seem to work for me so I'm trying to debug your extension under VSCode debugger. While I've managed to to this for the extension itself (I can set a breakpoint in src.extension.ts, watch variables etc.), I cannot do that for src/debug/debug.ts. I'm quite new to VSCode/typescript/node.js etc. so I'm sorry for probably dump question: how to debug src/debug/debug.ts?

@hackwaly
Copy link
Owner

hackwaly commented Jun 23, 2016

I'm sorry but I've tested that works on my Win10 VM.

About debug: please reference this. https://github.com/Microsoft/vscode-go/tree/master/src/debugAdapter.

@hackwaly hackwaly reopened this Jun 23, 2016
@db4
Copy link
Contributor Author

db4 commented Jun 23, 2016

Hmm, I've tried that but got

node --debug-brk=48532 ..\..\out\src\debug\debug.js --server=4711 
Debugger listening on port 48532
u:\Work\vscode-ocaml\out\src\debug\debug.js:208
            for (let { line, column } of args.breakpoints) {
                     ^

SyntaxError: Unexpected token {
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:373:25)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Module.runMain [as _onTimeout] (module.js:441:10)

while running debug-debugger. Probably I'm doing something wrong?

@hackwaly
Copy link
Owner

Update your nodejs runtime. Currently Typescript didn't support async/await in ES5 target. microsoft/TypeScript#1564 You need a version of nodejs support most ES6 features.

@db4
Copy link
Contributor Author

db4 commented Jun 23, 2016

Thanks, I've finally made the vscode debugger working. What I see - in

        }, (buffer: string) => {
            if (!this._debuggeeProc && !this._remoteMode && buffer.includes('Waiting for connection...')) {

you get buffer with (ocd) Loading program.., not the whole (ocd) Loading program...\nWaiting for connection...(the socket is 127.0.0.1:12345). Maybe due to timing issues you are just missing the second line? IMO you should be waiting for Waiting for connection string after goto 0 command.

@hackwaly
Copy link
Owner

hackwaly commented Jun 23, 2016

readUntilPrompt will read until found last line is "(ocd) ". So it won't miss "Waiting for connection...".
I think previously you can't get debugger working is caused by nodejs runtime. After you updated nodejs, It should work. Did you check it?

@db4
Copy link
Contributor Author

db4 commented Jun 23, 2016

readUntilPrompt will read until found last line is "(ocd) ". So it won't miss "Waiting for connection..."

I've just told you what I really saw in the debugger; tomorrow I will try to provide more details.

I think previously you can't get debugger working is caused by nodejs runtime. After you updated nodejs, It should work. Did you check it?

It doesn't. Yes, I've upgraded node.js to version 6.2.2

@hackwaly
Copy link
Owner

I'm very sorry for that!

Today I checked it on Windows again. It seems that sometime work, sometime doesn't. I'm too "luck" yesterday and I didn't check that many times.

I'll fix this today. Thank you!

@hackwaly
Copy link
Owner

It seems that we must introduce state machine as OcaIDE does to solve this problem.

@hackwaly
Copy link
Owner

Debugger implementation may need refactor in the future.

I temporarily fix that so you can use it instantly. Try version 0.4.4.

@db4
Copy link
Contributor Author

db4 commented Jun 24, 2016

It still doesn't work. What I now see in the debug log is

ocd: "\tOCaml Debugger version 4.02.3\n\n(ocd) "
cmd: goto 0
ocd: "\tOCaml Debugger version 4.02.3\n\n(ocd) "
ocd: "Loading program... "
ocd: "Loading program... "
cmd: run
ocd: "Loading program... "
ocd: "Loading program... "
cmd: backtrace 100
ocd: "Loading program... "
ocd: "Loading program... "

@hackwaly
Copy link
Owner

hackwaly commented Jun 24, 2016

Try fully restart VS Code. I used to encounter this problem too.

EDIT: Test if ocamldebug works without VS Code.

@db4
Copy link
Contributor Author

db4 commented Jun 24, 2016

Of course I did that. I still think that something is wrong with your ocamldebug communication logic and an unexpected delay exposes the bug. You're waiting for (ocp) as a result of any ocamldebug command, right? That's not the case for goto 0 in loadingmode=manual, it does not issue (ocd) in the end. Instead, you should be waiting for Waiting for connection..., then start the debuggee and only then (ocd) will be returned.

@hackwaly
Copy link
Owner

hackwaly commented Jun 24, 2016

You are right. The logic nothing difference than you say.
goto 0 wait for (ocd) prompt and monitor the intermediate output before got (ocd) prompt. If it see debugger suspend with "Waiting for connection...", then start the debuggee, then debugger resumed.

The log you given says that ocamldebug doesn't load debuggee succeed. So I asked you to check if ocamldebug works standalone.

The temporary fix introduce a magic number - debounce timeout 64 ms. This may be a hidden problem. You can change it to 1000ms or more long to test if the problem is that.

To prove it works on my Windows OS. I paste a gif here.
debugger

@hackwaly
Copy link
Owner

I'm wrong. The problem is "Loading program... (ocd) " response early break the goto 0 command. So the communication logic should be rewrite to make things right.

@hackwaly
Copy link
Owner

@db4, It looks like you set "socket": "127.0.0.1:12345" in your launch configuration? Do not set socket property.

If you set it. You must manual launch debuggee ( "CAML_DEBUG_SOCKET=127.0.0.1:12345" ./main.d.byte).

@db4
Copy link
Contributor Author

db4 commented Jun 24, 2016

It looks like you set "socket": "127.0.0.1:12345" in your launch configuration?

No, I didn't. I just replaced a random port with '12345' in my comment. Probably it was a bad idea that confused you.

@hackwaly
Copy link
Owner

hackwaly commented Jun 24, 2016

Try 0.4.6! If it still doesn't work. I'll rewrite debug logic in weekend.

@db4
Copy link
Contributor Author

db4 commented Jun 24, 2016

Still doesn't work. What I noticed is that when I run ocamldebug an manually issue set loadingmode manual, goto 0, there is some delay (a fraction of second, but still) between Loading program... and Waiting for connection..., So you probably stop waiting for an answer before Waiting for connection... arrives.

@hackwaly
Copy link
Owner

hackwaly commented Jun 24, 2016

Does it work on a simple helloworld program? I'm going to write a proxy of ocamldebug to simulate the delay.

@db4
Copy link
Contributor Author

db4 commented Jun 24, 2016

No, it doesn't - looks like the same problem. Maybe my %PATH% that's quite long, is responsible for that?

@hackwaly
Copy link
Owner

hackwaly commented Jun 25, 2016

Which OCaml distribution do you use? I'm trying to reproduce the problem.

@db4
Copy link
Contributor Author

db4 commented Jun 27, 2016

OCaml 4.02.3 (built with MSVC from sources)

Well, I'm trying to debug the issue myself. As I'm absolute newbie to (java|type)script, can you explain how

        this._wait = this.readUntilPrompt().then(() => { });
        this.ocdCommand(['set', 'loadingmode', 'manual'], () => { });

guaranties that you wait for (ocd) first and only THEN issue set loadingmode manual? In my debugging session readUntilPrompt() takes first response from ocamldebug AFTER set loadingmode manual is issued.

@hackwaly
Copy link
Owner

this._wait is a Promise. this.ocdCommand will await this._wait completed then this._debuggerProc.stdin.write(cmd + '\n'), and return this.readUntilPrompt as new this._wait.

    ocdCommand(cmd, callback, callback2?) {
        if (Array.isArray(cmd)) {
            cmd = cmd.join(' ');
        }

        this._wait = this._wait.then(() => {
            log(`cmd: ${cmd}`);
            this._debuggerProc.stdin.write(cmd + '\n');
            return this.readUntilPrompt(callback2).then((output) => { callback(output) });
        });
    }

So

        this._wait = this.readUntilPrompt().then(() => { });
        this.ocdCommand(['set', 'loadingmode', 'manual'], () => { });

Will first read until (ocd) prompt, then issue set loadingmode manual command.


Could you please provide your log again? ocdCommand being called doesn't mean the command was issued.

@db4
Copy link
Contributor Author

db4 commented Jun 28, 2016

Let me clarify my question. Consider the following start of ocamldebug session:

C:\Work\>ocamldebug hello.exe
        OCaml Debugger version 4.02.3

(ocd) set loadingmode manual
(ocd) goto 0
Loading program...
Waiting for connection...(the socket is 127.0.0.1:10232)

In your code

        this._wait = this.readUntilPrompt().then(() => { });

is expected to catch OCaml Debugger version 4.02.3\n(ocd) and THEN

        this.ocdCommand(['set', 'loadingmode', 'manual'], () => { });

is expected to issue set loadingmode manual command. What makes them execute in sequence? Their promises are not chained and set loadingmode manual command can be easily output BEFORE ocamldebug tells it's ready to process commands.

@hackwaly
Copy link
Owner

hackwaly commented Jun 28, 2016

this._wait = this.readUntilPrompt().then(() => { }); is same as this._wait = this.readUntilPrompt();. I add .then(() => { }); just for passing type check.

If a callback passed to then don't return a Promise, it considered then will return a new Promise that will completed after the receiver promise complete and the callback be called. If the callback do return a Promise, the Promise then returned will also wait for that promise complete.

@db4
Copy link
Contributor Author

db4 commented Jun 28, 2016

OK, I've finally found the problem. In

            ocdArgs.push('cd', args.cd);

there is a typo, it should be

            ocdArgs.push('-cd', args.cd);

So then I specified cd attribute in launch.json configuration, ocamldebug got incorrect command line and behaved incorectly. Now it seems to work.

@hackwaly
Copy link
Owner

hackwaly commented Jun 28, 2016

Thank you. I'm sorry to waste a lot of your time. Fixed in 0.4.7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants