Skip to content

服务器无法正常关闭 #15

@vecljox

Description

@vecljox

您好,非常感谢您的cpp-mcp项目,它对我非常有帮助。我希望能够自由地启动与关闭 MCP Server。在调用 start() 方法时,我选择的是非阻塞模式(即 blocking=false),服务器可以正常启动。但在调用 server::stop() 方法尝试关闭服务器时,程序会阻塞在

maintenance_thread_->join();

该线程中包含一个 std::this_thread::sleep_for(std::chrono::seconds(60)); 所以 join() 被阻塞了最长 60 秒,对此我使用了条件变量来唤醒休眠的maintenance_thread

maintenance_thread_ = std::make_unique<std::thread>([this]() {
    std::unique_lock<std::mutex> lock(maintenance_mutex_);
    while (running_) {
        // Check inactive sessions every 60 seconds
        if (maintenance_cv_.wait_for(lock, std::chrono::seconds(60), [this] {
              return !running_ || stop_requested_;
            }))
        {
          break;
        }

        if (running_) {
            lock.unlock();
            try {
                check_inactive_sessions();
            } catch (const std::exception& e) {
                LOG_ERROR("Exception in maintenance thread: ", e.what());
            } catch (...) {
                LOG_ERROR("Unknown exception in maintenance thread");
            }
            lock.lock();
        }
    }
});

我不确定这么做是否正确,但是不会因此而阻塞了。坏消息是程序大概执行了1s后就发生了崩溃,崩溃点以及异常信息如下

thread->join();

void join() {
    if (!joinable()) {
        _Throw_Cpp_error(_INVALID_ARGUMENT);
    }

    if (_Thr._Id == _Thrd_id()) {
        _Throw_Cpp_error(_RESOURCE_DEADLOCK_WOULD_OCCUR);
    }

    if (_Thrd_join(_Thr, nullptr) != _Thrd_result::_Success) {     // ← crash here
        _Throw_Cpp_error(_NO_SUCH_PROCESS);
    }

    _Thr = {};
}

0x00007FFDF7B50E4A (ntdll.dll)处(位于 server_example.exe 中)引发的异常: 0xC0000008: An invalid handle was specified。

我在调试器里看到此时的thread的id为0,似乎已经是处于无效状态。

除此以外,我在查看server::stop()还有个小疑问,

cpp-mcp/src/mcp_server.cpp

Lines 110 to 140 in 86856a2

// Copy all dispatchers and threads to avoid holding the lock for too long
std::vector<std::shared_ptr<event_dispatcher>> dispatchers_to_close;
std::vector<std::unique_ptr<std::thread>> threads_to_join;
{
std::lock_guard<std::mutex> lock(mutex_);
// Copy all dispatchers
dispatchers_to_close.reserve(session_dispatchers_.size());
for (const auto& [_, dispatcher] : session_dispatchers_) {
dispatchers_to_close.push_back(dispatcher);
}
// Copy all threads
threads_to_join.reserve(sse_threads_.size());
for (auto& [_, thread] : sse_threads_) {
if (thread && thread->joinable()) {
threads_to_join.push_back(std::move(thread));
}
}
// Clear the maps
session_dispatchers_.clear();
sse_threads_.clear();
session_initialized_.clear();
}
// Close all sessions
for (const auto& [session_id, _] : session_dispatchers_) {
close_session(session_id);
}

session_dispatchers_已经clear掉了,后续的对session_dispatchers_的遍历然后close_session(session_id);作用是什么呢?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions