netcoredbg icon indicating copy to clipboard operation
netcoredbg copied to clipboard

Cannot receive request in VSCode mode

Open fenixjiang opened this issue 4 years ago • 29 comments

  1. Start netcoredbg with arg: "--interpreter=vscode --server"
  2. My DapClient like this: 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 !!!
  3. In server side(vscodeprotocol.cpp) at func 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.

fenixjiang avatar Oct 25 '21 05:10 fenixjiang

@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 avatar Oct 25 '21 19:10 alpencolt

@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. getline

I don't know what to do next. Any suggestions?

fenixjiang avatar Oct 26 '21 02:10 fenixjiang

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 avatar Oct 26 '21 09:10 viewizard

@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.

fenixjiang avatar Oct 26 '21 10:10 fenixjiang

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

alpencolt avatar Oct 26 '21 10:10 alpencolt

I suggest to record communication between two parties by using tcpdump (wireshark, etc...) or strace. Devil might hide in the details.

0xfk0 avatar Oct 26 '21 13:10 0xfk0

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).

0xfk0 avatar Oct 26 '21 14:10 0xfk0

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.

0xfk0 avatar Oct 26 '21 14:10 0xfk0

@kfrolov I found the problem according to your suggestion. The file type is socket, overlapped I/O. The Class::readmethod 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::Readthe 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 StreamBufmay 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 avatar Oct 28 '21 01:10 fenixjiang

@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.

viewizard avatar Oct 28 '21 09:10 viewizard

@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) ?

0xfk0 avatar Oct 28 '21 13:10 0xfk0

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.

0xfk0 avatar Oct 28 '21 13:10 0xfk0

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.

fenixjiang avatar Nov 03 '21 09:11 fenixjiang

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().

fenixjiang avatar Nov 03 '21 09:11 fenixjiang

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 avatar Nov 03 '21 09:11 viewizard

@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.

0xfk0 avatar Nov 08 '21 12:11 0xfk0

@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.

alpencolt avatar Nov 12 '21 17:11 alpencolt

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 avatar Nov 15 '21 09:11 fenixjiang

@fenixjiang check latest release we've fixed some issues on windows platform

alpencolt avatar Dec 10 '21 14:12 alpencolt

@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).

fenixjiang avatar Dec 15 '21 09:12 fenixjiang

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 avatar Jun 07 '22 15:06 viewizard

@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.

fenixjiang avatar Jun 09 '22 09:06 fenixjiang

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.

viewizard avatar Jun 09 '22 09:06 viewizard

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 <[email protected]>
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 avatar Jun 10 '22 15:06 viewizard

@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 avatar Jun 14 '22 05:06 fenixjiang

@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.

alpencolt avatar Jun 14 '22 14:06 alpencolt

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_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."

0xfk0 avatar Jun 14 '22 14:06 0xfk0

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 };
}	

}

fenixjiang avatar Jun 16 '22 01:06 fenixjiang