google / google/cppdap

Sometimes a closed Socket::Shared reads indefinitely and does not close session endpoint (part two)

Abierto
#154 2 comentarios 0 reacciones 0 asignados Ver en GitHub
Lenguaje dominante
C++
Estrellas
192
Forks
66
Métricas de merge de PR
Sin PR fusionados en 30 d

Descripción

Ref: https://github.com/google/cppdap/issues/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 https://github.com/google/cppdap/compare/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]

```cpp
#include
#include
#include
#include
#include
#include
#include
#include

#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 lock(mutex);
cv.wait(lock, [&] { return fired; });
}

void Event::fire() {
std::unique_lock lock(mutex);
fired = true;
cv.notify_all();
}

Event terminate;
std::vector 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& 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:
https://github.com/google/cppdap/blob/6464cd7bd0a5639b11902055ca607b53915833fc/src/socket.cpp#L208-L209

The loop comes from here, where `reader.isOpen()` is `true`, but `getPayload()` is empty:
https://github.com/google/cppdap/blob/6464cd7bd0a5639b11902055ca607b53915833fc/src/session.cpp#L87-L91

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

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.