-
Notifications
You must be signed in to change notification settings - Fork 62
Description
Ref: #101
I'm still having this issue sometimes, at least on Mac OS X (Sonoma 14.0). I'm using commit 82beeea and there doesn't seem to have been any relevant changes since then 82beeea...main
Here's an example server:
hello_debugger.cpp
[I know it's not the best code with the condition variables but it shows the issue I'm facing]
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <condition_variable>
#include <iostream>
#include <thread>
#include <vector>
#include "dap/io.h"
#include "dap/network.h"
#include "dap/protocol.h"
#include "dap/session.h"
class Event {
public:
// wait() blocks until the event is fired.
void wait();
// fire() sets signals the event, and unblocks any calls to wait().
void fire();
private:
std::mutex mutex;
std::condition_variable cv;
bool fired = false;
};
void Event::wait() {
std::unique_lock<std::mutex> lock(mutex);
cv.wait(lock, [&] { return fired; });
}
void Event::fire() {
std::unique_lock<std::mutex> lock(mutex);
fired = true;
cv.notify_all();
}
Event terminate;
std::vector<std::thread> threads;
void my_handler(int s) {
printf("Caught signal %d\n", s);
terminate.fire();
}
int main(int argc, char** argv) {
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = my_handler;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
auto _server = dap::net::Server::create();
auto address = "0.0.0.0";
auto started = _server->start(
address, 12345, [&](const std::shared_ptr<dap::ReaderWriter>& rw) {
threads.emplace_back([=] {
auto session = dap::Session::create();
session->onError([&](const char* msg) {
std::cout << "Session error: " << msg << "\n";
terminate.fire();
});
session->bind(rw,
[&]() { std::cout << "Session endpoint closed\n"; });
terminate.wait();
});
});
if (!started) {
std::cerr << "Failed to start DAP server.\n";
_server.reset();
}
sigaction(SIGINT, &sigIntHandler, NULL);
terminate.wait();
std::cout << "Exiting\n";
for (auto& thread : threads) {
thread.join();
}
return 0;
}When I run the server and nc localhost 12345 and then Ctrl+C the nc process, my CPU usage flies through the roof, and it looks like there is still an infinite read:
* thread #6, stop reason = breakpoint 3.1
* frame #0: 0x000000010008a520 hello_debugger`dap::Socket::Shared::read(this=0x000000013ef044e8, buffer=0x0000000170142c78, bytes=15) at socket.cpp:210:13
frame #1: 0x000000010000d678 hello_debugger`dap::ContentReader::buffer(this=0x0000000140104390, bytes=15) at content_stream.cpp:151:27
frame #2: 0x000000010000d8b4 hello_debugger`dap::ContentReader::scan(this=0x0000000140104390, seq="Content-Length:", len=15) at content_stream.cpp:96:10
frame #3: 0x000000010000d4c0 hello_debugger`dap::ContentReader::scan(this=0x0000000140104390, str="Content-Length:") at content_stream.cpp:107:10
frame #4: 0x000000010000d1d8 hello_debugger`dap::ContentReader::read(this=0x0000000140104390) at content_stream.cpp:56:10
Again, the recv() call is returning 0 on the closed socket:
Lines 208 to 209 in 6464cd7
| auto len = | |
| recv(s, reinterpret_cast<char*>(buffer), static_cast<int>(bytes), 0); |
The loop comes from here, where reader.isOpen() is true, but getPayload() is empty:
Lines 87 to 91 in 6464cd7
| while (reader.isOpen()) { | |
| if (auto payload = getPayload()) { | |
| inbox.put(std::move(payload)); | |
| } | |
| } |
I say sometimes this issue happens because sometimes the session ClosedHandler does execute ... other times, it hangs in this loop forever. Under no circumstance is the session error handler triggered.