Open fenixjiang opened 2 years ago
@fenixjiang as I understand you write your own plugin for VSCode. According to source code you trying to pass null
to NetCoreDbg which sets failbit
in cin
(check). You should pass VSCode protocol commands instead.
@viewizard could share where to look them?
@alpencolt Thank you for your reply!
Here is a Dap implementation include a DebugAdapterClient( https://github.com/OmniSharp/csharp-language-server-protocol).
I think as far as netcoredbg supports vscode mode, then it should be able to receive messages from dap Client. In fact, it did receive/respond the message from/to my DapClient, but it need to set a breakpoint on the socket connect, and wait for the DapClient send the initialize command. Without this breakpoint, the previous situation will occur.
I set a breakpoint on if(! cin.good())
at method std::string VSCodeProtocol::ReadData()
, I can see my initialize request in the cin.
I don't know what to do next. Any suggestions?
I set a breakpoint on if(! cin.good()) at method std::string VSCodeProtocol::ReadData(), I can see my initialize request in the cin.
As I see, debugger execute code inside !cin.good()
code block after you command received, that mean you work with cin
in wrong way and this is not related to command you sent.
More you could read here: https://en.cppreference.com/w/cpp/io/basic_ios/good
@viewizard I don't know how to get that command in the cin.
I tried call cin.Ignore()
cin.clear()
before std::getline()
. I use cin.seekg()
to move the position. I make a endless loop to read buff from cin, but i can't get that command string.
Check what you send on plugin side, you send something that makes cin !good
, probably it's null
or EOF
.
Also you can print line
on debugger side to check what comes
I suggest to record communication between two parties by using tcpdump (wireshark, etc...) or strace. Devil might hide in the details.
Which file type is used for netcoredbg's stdin/stdout in your case? This is socket, named pipe, anonymous (unnamed) pipe, something other?
I suspect, we may have issue with unnamed pipes on windows: "Asynchronous (overlapped) read and write operations are not supported by anonymous pipes". (see https://docs.microsoft.com/en-us/windows/win32/ipc/anonymous-pipe-operations)
Can you switch to using of named pipes or sockets in place of stdin/stderr? See unnamed_pair
function (in iosystem_win32.cpp
) as an example, how to create pair of named pipes.
Try to set up breakpoints in iosystem_win32.cpp
, in async_read
function and check, that return {}
never executes (this means an error). Also check, that Class::read
function never returns error (ReadFile
API call might return error).
Please rebuild netcoredbg in Debug mode and enable full logs (as described here: https://github.com/Samsung/netcoredbg). Then reproduce the issue, record the log and attach the log to this bug report. This is the first thing you should do. If some errors occurs within IORedirect
and IOSystem
, IOSystemTraits<T>
classes, these errors must be logged.
@kfrolov I found the problem according to your suggestion. The file type is socket, overlapped I/O.
The Class::read
method in iosystem_win32.cpp
returnERROR_IO_PENGDING
, and i didn'see where it was processed.
Because I don’t know where is the best place to processed with it, so i directly modified Class::Read
the method, call GetOverlappedResult
while last error is ERROR_IO_PENDING
.
Class::IOResult Class::read(const FileHandle& fh, void *buf, size_t count)
{
DWORD dwRead = 0;
OVERLAPPED ov = {};
if (!ReadFile(fh.handle, buf, (DWORD)count, &dwRead, &ov))
{
//return { (GetLastError() == ERROR_IO_PENDING ? IOResult::Pending : IOResult::Error), dwRead };
DWORD lastError = GetLastError();
if (lastError == ERROR_IO_PENDING)
{
if (!GetOverlappedResult(fh.handle, &ov, &dwRead, TRUE))
return { IOResult::Error, dwRead };
}
else
return { IOResult::Error, dwRead };
}
return { (dwRead == 0 ? IOResult::Eof : IOResult::Success), dwRead };
}
After this modification, netcoredbg
can communicate with my Dap client.
Now there is a new problem. After sending and receiving more than 10 messages, the 'ReadFile' inClass::read
return ERROR_WORKING_SET_QUOTA
. The cout.flush()
failed in VSCodeprotocol::EmitEvent()
. I debug into flush
in ostream
:line548, const sentry _Ok(*this)
is false.
I guess the default buffer size of StreamBuf
may be too small, so I increased the buff to 1M, but the problem is still the same.
I am looking for the reason why flush
failed.
Is my modification about ERROR_IO_PENDING
correct? what is the best practice?
@fenixjiang you could find working C# example here - https://github.com/Samsung/netcoredbg/tree/master/test-suite Our test suite framework aimed to network and local interaction with debugger by VSCode and MI/GDB protocols. For example, VSCode network part looks like: https://github.com/Samsung/netcoredbg/blob/master/test-suite/NetcoreDbgTest/VSCode/VSCodeTcpDebuggerClient.cs
Hope this helps.
@fenixjiang, IOResult::Pending error is processed here: https://github.com/Samsung/netcoredbg/blob/2de336c9496f6b3e8817ed19c70a9d957b8afc43/src/utils/streams.cpp#L95 As you can see, in case of such error, code just loops until read opeation will be finished. So I not understood, why this error raises through InStreamBuf class up to std::streambuf and cin
starts reporting an error.
Look strange, as ERROR_WORKING_SET_QUOTA
error, which is caused by multiple calls to ReadFile
without calling GetOverlappedResult
(which you have added). I suspect, that GetOverlappedResult
must be called every time, even if ReadFile
returns True
.
As I understood, IOSystemTraits<Win32PlatformTag>::read
and write
function call ReadFile
and WriteFile
with non NULL OVERLAPPED
argument because of sockets: OVERLAPPED
not needed for other file types, but for sockets it is needed, otherwise ReadFile
or WriteFile
will fail. This is why OVERLAPPED have non-null in synchronous read/write functions. I suspect, this is because WinSock2 library open sockets in asynchronous (with
FILE_FLAG_OVERLAPPED` mode).
Microsoft's documentation says (https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile), "The lpOverlapped parameter must not be NULL..." if file opened with FILE_FLAG_OVERLAPPED
set.
And you a right, that GetOverlappedResult(..., bWait=1)
must be called to wait for a result. And I suspect, that it must be called even if ReadFile
returns True
. Also microsoft documentation says, that lpNumberOfBytesRead
must be set to NULL
(when calling ReadFile
) if you are using overlapped IO.
And I think, same is correct for WriteFile
. So you must patch both functions, IOSystemTraits<Win32PlatformTag>::read
and write
.
I curious, why ERROR_IO_PENDING
was never raised in our cases. Looks like you have very different Windows version, WinSock2 library, etc... Which exact windows version are you using? Can you reproduce the bug on regular Windows-10 version?
And last question, how are you running netcoredbg? The sockets for cin
/cout
was opened by netcoreddbg itself (by call to IOSystem::listen_socket
, that happens if you are passing --server
option to netcoredbg), or you create sockets by itself and pass opened sockets from your program to child process (which is netcoredbg) ?
flush
function calls OutStreamBuf::sync()
, which calls IOSystem::write
, which in fact is IOSystemTraits<Win32PlatformTag>::write
. I think the problem is same, win32 function WriteFile
returns an error because you have not called GetOverlappedResult
, but OVERLAPPED
is not null.
Here is my test program with VSCodeTcpDebuggerClient
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var tcpClient = new VSCodeTcpDebuggerClient("127.0.0.1", 4711);
var debugger = new VSCodeDebugger(tcpClient);
//init
InitializeRequest initReq = new InitializeRequest();
initReq.arguments.clientID = "myTest";
initReq.arguments.clientName = "My Test";
initReq.arguments.adapterID = "coreclr";
//initReq.arguments.pathFormat = "path";
//initReq.arguments.linesStartAt1 = true;
//initReq.arguments.columnsStartAt1 = true;
initReq.arguments.supportsVariableType = true;
initReq.arguments.supportsVariablePaging = true;
initReq.arguments.supportsRunInTerminalRequest = true;
//initReq.arguments.supportsProgressReporting = true;
//initReq.arguments.supportsMemoryReferences = true;
//initReq.arguments.locale = "en-us";
var result = debugger.Request(initReq);
//breaks;
var bp = new SetBreakpointsRequest();
var file = @"D:\Github\Debugger\Test\ConsoleApp16\ConsoleApp2_2\Program.cs";
bp.arguments.source.path = file;
bp.arguments.source.name = System.IO.Path.GetFileName(file);
bp.arguments.breakpoints.Add(new SourceBreakpoint(11));
var bpRet = debugger.Request(bp);
//launch
LaunchRequest launchReq = new LaunchRequest();
//launchReq.arguments.name = "Test my console";
//launchReq.arguments.type = "coreclr";
//launchReq.arguments.preLaunchTask = "build";
launchReq.arguments.program = @"C:\Program Files\dotnet\dotnet.exe";
launchReq.arguments.cwd = @"D:\Github\Debugger\Test\ConsoleApp16\ConsoleApp2_2\bin\Debug\netcoreapp2.2";
launchReq.arguments.args = new System.Collections.Generic.List<string>() { "exec", "D:\\Github\\Debugger\\Test\\ConsoleApp16\\ConsoleApp2_2\\bin\\Debug\\netcoreapp2.2\\ConsoleApp2_2.dll", "AAAA", "BBB" };
launchReq.arguments.env = new System.Collections.Generic.Dictionary<string, string>();
//launchReq.arguments.console = "internalConsole";
//launchReq.arguments.stopAtEntry = true;
//launchReq.arguments.internalConsoleOptions = "openOnSessionStart";
//launchReq.arguments.__sessionId = Guid.NewGuid().ToString();
var r1 = debugger.Request(launchReq);
//configrationDone
var cfgDone = new ConfigurationDoneRequest();
var cfgRet = debugger.Request(cfgDone);
//Please ignore those, just to print the messages
while (true)
{
if (!debugger.IsEventReceived(OnEventReceived))
Task.Delay(500).Wait();
}
_ = Console.ReadLine();
}
And I get the same result. After netcoredbg sends a few messages, in my case it was 8, then vscodeprotocol.cpp/cout.flush fail and cout.eof()
return true
.
I thought there might be a bug here.
I modified this VSCodeProtocol::EmitEvent method, call cout.clear()
after cout.flush()
, and communication is normal now.
void VSCodeProtocol::EmitEvent(const std::string &name, const nlohmann::json &body)
{
std::lock_guard<std::mutex> lock(m_outMutex);
json response;
response["type"] = "event";
response["event"] = name;
response["body"] = body;
std::string output = response.dump();
output = VSCodeSeq(m_seqCounter) + output.substr(1);
++m_seqCounter;
cout << CONTENT_LENGTH << output.size() << TWO_CRLF << output;
cout.flush();
cout.clear(); //<-----Add this line!!!
Log(LOG_EVENT, output);
}
For now I have not found the reason why the eof
status is set after cout.flush()
.
We definitely will not add some code just because this change behavior in the way you need. I don't see any reason for cout.clear();
line here. The point is - this could be another issue, that you suppress by this line, but not provide real fix. This issue must be investigated first in order to find out why only you have eof
here.
@viewizard, I think you need to test netcoredbg running on Windows-7 and may be on Windows-Vista or Windows-XP. I guess, that all issues caused by overlapped IO which works differently on same previous Windows version.
cout.clear()
works, because cout.flush()
causes an error. In our case flush
ends with call to WriteFile
with non-NULL overlapped
argument.
I think @fenixjiang uses some "non typical" windows version (installed libraries, other environment related things...) And this is why the bug was not meet in our cases.
@fenixjiang we cannot call clear()
since it removes all flags from stream, but they are useful for case when IDE hangs. we must handle such situation.
What Windows version do you use?
Also could you disable all firewalls and antiviruses. If it doesn't help could you check passed data via WireShark or other sniffer.
Sorry for replying so late. My windows version is 10.0.18363.1916, and dotnet sdks version is 5.0.302.
I thought my client may be used incorrectly. I haven't seen other people having the same problem as mine in message transmission. Transmission is a very basic function, and there should not be such a problem. The preconceived ideas have kept me from finding the root of the problem. The changes I made before are probably just to solve the superficial problem.
@fenixjiang check latest release we've fixed some issues on windows platform
@alpencolt I had check the latest release, but my problem still exists.
I start netcoredbg with arguments "--interpreter=vscode --server", then connect it with a dap client (https://github.com/OmniSharp/csharp-language-server-protocol).
netcoredbg exit while init request
is send. netcoredbg does not process any command.
GetLastError()
is ERROR_IO_PENDING
after call function ReadFile
in Class::read
in file iosystem_win32.cpp . ERROR_IO_PENDING
is not considered as IOResult::Error
. The loop in InStreamBuf::underflow
in file streams.cpp can continued to call ReadFile
,
after a while, GetLastError()
after call ReadFile
return ERROR_NOT_ENOUGH_QUOTA
, this is considered as IOResult::Error
that make InStreamBuf:::underflow
return eof
, then VSCodeprotocol::CommandLoop
return.
During my debugging, I find it does not call GetOverlappedResult
while the last error is ERROR_IO_PENDING
as Microsoft's documentation says (https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile).
I updated upstream sources, it should support Windows 10 x86 now. Could you please confirm, that you still have this issue with latest sources?
@viewizard
I have checked out the lastest sources, and build successfully under Win10 x86. The following problem occurred when experiencing the new features:
I started netcoredbg with --interpreter=cli --hot-reload
,then debug a simple console.
we got a assertion failed.
ncdb> file C:\Users\jz\source\repos\ConsoleApp1\ConsoleApp1\bin\Debug\net5.0\ConsoleApp1.exe
ncdb> b C:\Users\jz\source\repos\ConsoleApp1\ConsoleApp1\Program.cs:17
ncdb> run
Assertion failed: !read_lock, file C:\Work\netcoredbg_v78\src\utils\ioredirect.cpp, line 404
Then i try start netcoredbg directly from VS2019, still have above issue.
I will try this under Win10 x64 , and run netcoredbg in vscode mode later.
Note, we support Hot Reload feature for Tizen OS only, since it required custom runtime build + you will need generate IL/metadata/PDB deltas somehow, and even for Tizen OS it have WIP status.
Here is patch that fix issue with Assertion failed: !read_lock, file C:\Work\netcoredbg_v78\src\utils\ioredirect.cpp, line 404
From 28defb5d7130d1f7a6736c46e5f7eb177743c010 Mon Sep 17 00:00:00 2001
From: Mikhail Kurinnoi <m.kurinnoi@samsung.com>
Date: Fri, 10 Jun 2022 18:01:42 +0300
Subject: [PATCH] Fix CLI work on Windows.
---
src/utils/iosystem_win32.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/utils/iosystem_win32.cpp b/src/utils/iosystem_win32.cpp
index d206c6c..dc2d4e9 100644
--- a/src/utils/iosystem_win32.cpp
+++ b/src/utils/iosystem_win32.cpp
@@ -525,7 +525,7 @@ Class::IOSystem::StdFiles Class::get_std_files()
std::max_align_t align_field;
char mem[sizeof(Handles)];
};
- mem_align_t mem_align_tmp;
+ static mem_align_t mem_align_tmp;
char * const mem = mem_align_tmp.mem;
Handles& handles = *new (mem) Handles {
--
2.25.1
will be in upstream at next sync.
@viewizard I tred run netcoredbg under vscode mode, and still has transmission issue. These are netcoredbg received and output:
-> (C) {"seq":1,"type":"request","command":"initialize","arguments":{"clientID":"netcoredbg ClientId","clientName":"netcoredbg Client","adapterID":"netcoredbg AdapterId","supportsVariableType":true,"supportsVariablePaging":true,"supportsRunInTerminalRequest":true,"supportsMemoryReferences":true,"supportsProgressReporting":true}}
<- (E) {"body":{"capabilities":{"exceptionBreakpointFilters":[{"filter":"all","label":"all"},{"filter":"user-unhandled","label":"user-unhandled"}],"supportTerminateDebuggee":true,"supportsCancelRequest":true,"supportsConditionalBreakpoints":true,"supportsConfigurationDoneRequest":true,"supportsExceptionFilterOptions":true,"supportsExceptionInfoRequest":true,"supportsExceptionOptions":false,"supportsFunctionBreakpoints":true,"supportsSetExpression":true,"supportsSetVariable":true,"supportsTerminateRequest":true}},"event":"capabilities","seq":"1","type":"event"}
<- (E) {"body":{},"event":"initialized","seq":"2","type":"event"}
<- (R) {"body":{"exceptionBreakpointFilters":[{"filter":"all","label":"all"},{"filter":"user-unhandled","label":"user-unhandled"}],"supportTerminateDebuggee":true,"supportsCancelRequest":true,"supportsConditionalBreakpoints":true,"supportsConfigurationDoneRequest":true,"supportsExceptionFilterOptions":true,"supportsExceptionInfoRequest":true,"supportsExceptionOptions":false,"supportsFunctionBreakpoints":true,"supportsSetExpression":true,"supportsSetVariable":true,"supportsTerminateRequest":true},"command":"initialize","request_seq":1,"seq":"3","success":true,"type":"response"}
At this time code runs to vscodeprotocol.cpp
void VSCodeProtocol::CommandLoop()
{
std::thread commandsWorker{&VSCodeProtocol::CommandsWorker, this};
m_exit = false;
while (!m_exit)
{
std::string requestText = ReadData(cin);
if (requestText.empty())
{
CommandQueueEntry queueEntry;
queueEntry.command = "ncdbg_disconnect";
std::lock_guard<std::mutex> guardCommandsMutex(m_commandsMutex);
m_commandsQueue.clear();
m_commandsQueue.emplace_back(std::move(queueEntry));
m_commandsCV.notify_one(); // notify_one with lock
break; <------------------------------HERE!!!-----------
}
....
and in iosystem_win32.cpp Class::IOResult Class::read(const FileHandle& fh, void *buf, size_t count)
, the last error of ReadFile
is ERROR_WORKING_SET_QUOTA
.
Here are packages captured by wireshark
1 0.000000 kubernetes.docker.internal kubernetes.docker.internal TCP 56 11312 → trinity-dist(4711) [SYN] Seq=0 Win=65535 Len=0 MSS=65495 WS=256 SACK_PERM=1
2 0.000059 kubernetes.docker.internal kubernetes.docker.internal TCP 56 trinity-dist(4711) → 11312 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=65495 WS=256 SACK_PERM=1
3 0.000113 kubernetes.docker.internal kubernetes.docker.internal TCP 44 11312 → trinity-dist(4711) [ACK] Seq=1 Ack=1 Win=2619648 Len=0
4 0.011588 kubernetes.docker.internal kubernetes.docker.internal TCP 390 11312 → trinity-dist(4711) [PSH, ACK] Seq=1 Ack=1 Win=2619648 Len=346
5 0.011616 kubernetes.docker.internal kubernetes.docker.internal TCP 44 trinity-dist(4711) → 11312 [ACK] Seq=1 Ack=347 Win=2619648 Len=0
6 0.023814 kubernetes.docker.internal kubernetes.docker.internal TCP 626 trinity-dist(4711) → 11312 [PSH, ACK] Seq=1 Ack=347 Win=2619648 Len=582
7 0.023838 kubernetes.docker.internal kubernetes.docker.internal TCP 44 11312 → trinity-dist(4711) [ACK] Seq=347 Ack=583 Win=2619136 Len=0
8 0.025151 kubernetes.docker.internal kubernetes.docker.internal TCP 124 trinity-dist(4711) → 11312 [PSH, ACK] Seq=583 Ack=347 Win=2619648 Len=80
9 0.025171 kubernetes.docker.internal kubernetes.docker.internal TCP 44 11312 → trinity-dist(4711) [ACK] Seq=347 Ack=663 Win=2619136 Len=0
10 0.025626 kubernetes.docker.internal kubernetes.docker.internal TCP 643 trinity-dist(4711) → 11312 [PSH, ACK] Seq=663 Ack=347 Win=2619648 Len=599
11 0.025649 kubernetes.docker.internal kubernetes.docker.internal TCP 44 11312 → trinity-dist(4711) [ACK] Seq=347 Ack=1262 Win=2618368 Len=0
12 0.053768 kubernetes.docker.internal kubernetes.docker.internal TCP 400 11312 → trinity-dist(4711) [PSH, ACK] Seq=347 Ack=1262 Win=2618368 Len=356
13 0.053800 kubernetes.docker.internal kubernetes.docker.internal TCP 44 trinity-dist(4711) → 11312 [ACK] Seq=1262 Ack=703 Win=2619392 Len=0
14 0.058389 kubernetes.docker.internal kubernetes.docker.internal TCP 338 11312 → trinity-dist(4711) [PSH, ACK] Seq=703 Ack=1262 Win=2618368 Len=294
15 0.058415 kubernetes.docker.internal kubernetes.docker.internal TCP 44 trinity-dist(4711) → 11312 [ACK] Seq=1262 Ack=997 Win=2619136 Len=0
16 0.062129 kubernetes.docker.internal kubernetes.docker.internal TCP 486 11312 → trinity-dist(4711) [PSH, ACK] Seq=997 Ack=1262 Win=2618368 Len=442
17 0.062173 kubernetes.docker.internal kubernetes.docker.internal TCP 44 trinity-dist(4711) → 11312 [ACK] Seq=1262 Ack=1439 Win=2618624 Len=0
package No. 10 is the last response send from netcoredbg.
Content-Length: 576
{"body":{"exceptionBreakpointFilters":[{"filter":"all","label":"all"},{"filter":"user-unhandled","label":"user-unhandled"}],"supportTerminateDebuggee":true,"supportsCancelRequest":true,"supportsConditionalBreakpoints":true,"supportsConfigurationDoneRequest":true,"supportsExceptionFilterOptions":true,"supportsExceptionInfoRequest":true,"supportsExceptionOptions":false,"supportsFunctionBreakpoints":true,"supportsSetExpression":true,"supportsSetVariable":true,"supportsTerminateRequest":true},"command":"initialize","request_seq":1,"seq":"3","success":true,"type":"response"}
packages No.12, 14, 16 is not processed by netcoredbg. package details are below: No.12
Content-Length: 333
{"seq":2,"type":"request","command":"setBreakpoints","arguments":{"source":{"name":"CollectionTest.cs","path":"C:\\Users\\JiangZhen\\source\\repos\\ConsoleApp49\\ConsoleApp49\\CollectionTest.cs"},"breakpoints":[{"line":62,"column":17},{"line":90,"column":13},{"line":133,"column":9},{"line":155,"column":9},{"line":180,"column":3}]}}
No.14
Content-Length: 271
{"seq":3,"type":"request","command":"launch","arguments":{"program":"C:\\Users\\JiangZhen\\source\\repos\\ConsoleApp49\\ConsoleApp1\\bin\\Debug\\net6.0\\ConsoleApp1.exe","cwd":"C:\\Users\\JiangZhen\\source\\repos\\ConsoleApp49\\ConsoleApp1\\bin\\Debug\\net6.0","env":{}}}
No.16
Content-Length: 419
{"seq":4,"type":"request","command":"setExceptionBreakpoints","arguments":{"filters":["user-unhandled"],"filterOptions":[{"filterId":"all","condition":"System.NullReferenceException"},{"filterId":"all","condition":"System.Reflection.MissingMetadataException"},{"filterId":"all","condition":"System.Reflection.MissingRuntimeArtifactException"},{"filterId":"all","condition":"System.Windows.Markup.XamlParseException"}]}}
@fenixjiang command look right
I've found old discussion
https://alt.winsock.programming.narkive.com/dJgOGTYa/iocp-readfile-strange-error-error-working-set-quota
Most likely reason of ERROR_WORKING_SET_QUOTA
is some limitation on the system.
Please take a look at this question on stackoverflow: https://stackoverflow.com/questions/3442385/calls-to-readfile-return-error-working-set-quota
The problem is clearly described above in my comment from Oct 2021: _"Look strange, as ERROR_WORKING_SETQUOTA error, which is caused by multiple calls to ReadFile without calling GetOverlappedResult (which you have added). I suspect, that GetOverlappedResult must be called every time, even if ReadFile returns True."
From the very beginning, I modified the code according to kfrolov's suggestion to solve the communication problem in VSCode mode, so far it is running well, but I don't know if these modifications are the best practice.
Hereis my modifications:
// Function perform reading from the file: it may read up to `count' bytes to `buf'.
Class::IOResult Class::read(const FileHandle& fh, void *buf, size_t count)
{
//DWORD dwRead = 0;
//OVERLAPPED ov = {};
//if (! ReadFile(fh.handle, buf, (DWORD)count, &dwRead, &ov))
//return { (GetLastError() == ERROR_IO_PENDING ? IOResult::Pending : IOResult::Error), dwRead };
//else
//return { (dwRead == 0 ? IOResult::Eof : IOResult::Success), dwRead };
DWORD dwRead = 0;
OVERLAPPED ov = {};
ov.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!ReadFile(fh.handle, buf, (DWORD)count, 0, &ov))
{
if (GetLastError() == ERROR_IO_PENDING)
{
WaitForSingleObject(ov.hEvent, INFINITE);
CloseHandle(ov.hEvent);
if (GetOverlappedResult(fh.handle, &ov, &dwRead, TRUE))
{
DWORD err = GetLastError();
if ( err == ERROR_IO_PENDING
|| err == WAIT_TIMEOUT
|| err == ERROR_IO_INCOMPLETE)
{
return { dwRead == 0? IOResult::Pending : IOResult::Success, dwRead };
}
else
return { (dwRead == 0 ? IOResult::Eof : IOResult::Success), dwRead };
}
else
{
DWORD error = GetLastError();
return { ( error== ERROR_IO_PENDING || error == ERROR_IO_INCOMPLETE || error == WAIT_TIMEOUT ? IOResult::Pending : IOResult::Error), dwRead };
}
}
else
{
return { IOResult::Eof, dwRead };
}
}
else
{
return { (ov.InternalHigh == 0 ? IOResult::Eof : IOResult::Success), ov.InternalHigh };
}
}
var endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1", 4711));
var socket = new Socket(AdressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connent(endPoint);
var stream = new NetworkStream(socket);
var options = new DebugAdapterClientOptions().WithInput(stream).Withoutput(stream);
var client = DebugAdapterClinet.Create(options);
await client.Initialize(System.Threading.CancellationToken.None); <----run to here and block !!!
std::string VSCodeProtocol::ReadData()
{
...
std::getline(cin, line);
if(! cin.good())
{
//Always run to here, even if DapClinet is just connected, before sending the initialization command。
}
...
}
Is there anything I missed? I am not good at English, I hope my description clears up my problem. Thanks.