google / google/cppdap

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

Đang mở
#154 2 bình luận 0 reaction 0 người được giao Xem trên GitHub
Ngôn ngữ chính
C++
Star
192
Fork
66
Chỉ số merge pull request
Không có pull request nào được merge trong 30 ngày

Mô tả

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

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.