客户端上的Grpc访问冲突

问题描述 投票:0回答:1

我正在弄乱GRPC。当前,我正在使用C# Web应用程序作为GRPC服务器,并且正在使用C++控制台应用程序作为客户端。

我能够毫无问题地成功连接服务器并与之通信。问题出在我退出C++控制台客户端应用程序。退出时会抛出Access Violation

堆栈跟踪

MeterReaderClientCpp.exe!`anonymous namespace'::ThreadInternalsWindows::thread_body  
MeterReaderClientCpp.exe!__acrt_lock
ntdll.dll!RtlpWaitOnCriticalSection()
ntdll.dll!RtlpEnterCriticalSectionContended()
ntdll.dll!RtlEnterCriticalSection()
MeterReaderClientCpp.exe!__acrt_lock(__acrt_lock_id _Lock) Line 55
MeterReaderClientCpp.exe!_free_dbg(void * block, int block_use) Line 1019
MeterReaderClientCpp.exe!free(void * block) Line 32
MeterReaderClientCpp.exe!gpr_free(void * p) Line 53
MeterReaderClientCpp.exe!`anonymous namespace'::ThreadInternalsWindows::destroy_thread() Line 142
MeterReaderClientCpp.exe!`anonymous namespace'::ThreadInternalsWindows::Join() Line 112
MeterReaderClientCpp.exe!grpc_core::Thread::Join() Line 147
MeterReaderClientCpp.exe!gc_completed_threads() Line 74
MeterReaderClientCpp.exe!stop_threads() Line 331
MeterReaderClientCpp.exe!grpc_timer_manager_set_threading(bool threaded) Line 351
MeterReaderClientCpp.exe!grpc_shutdown_internal_locked() Line 175
MeterReaderClientCpp.exe!grpc_shutdown_internal(void * __formal) Line 208
MeterReaderClientCpp.exe!`anonymous namespace'::ThreadInternalsWindows::thread_body(void * v) Line 128

GRPC客户端

int main( )
{
    using namespace MeterReaderWeb::Services;
    using namespace google::protobuf::util;
    using namespace google::protobuf;


    std::cout << "Press enter\n";
    std::cin.ignore( );

    std::cout << "Calling Grpc service\n";

    std::fstream file{ R"(C:\Certificates\certificate.cer)", std::ios::in | std::ios::beg };
    if ( !file.is_open( ) )
    {
        std::cerr << "Failed to open file\n";
        return 1;
    }

    std::stringstream buffer;
    buffer << file.rdbuf( );

    grpc::SslCredentialsOptions options;
    options.pem_root_certs = buffer.str( );

    auto credentials{ grpc::SslCredentials( options ) };
    auto channel{ grpc::CreateChannel( "localhost:5001", credentials ) };
    auto stub{ MeterReadingService::NewStub( channel ) };

    ReadingPacket packet;
    packet.set_status( ReadingStatus::METER_READER_SUCCESS );
    packet.set_notes( "Here are some random notes" );

    auto message{ packet.add_readings( ) };    
    message->set_customer_id( 1 );
    message->set_reading_value( 10001 );

    auto timestamp{ message->mutable_reading_time( ) };
    timestamp->CopyFrom( TimeUtil::GetCurrentTime( ) );

    grpc::ClientContext context;
    StatusMessage response;
    if ( auto status{ stub->AddReading( &context, packet, &response ) }; status.ok( ) )
    {
        std::cout << "Added reading successfully\n";
        auto responseStatus{ response.status( ) };
        if ( responseStatus == ReadingStatus::METER_READER_SUCCESS )
        {
            std::cout << "Server status: success\n" 
                      << "Message: " << response.message( ) << '\n';

        }
    }
    else
    {
        std::cerr << "Error: " << status.error_message( ) << '\n';
        std::cerr << "Error Details: " << status.error_details( ) << '\n';
    }

    std::cin.ignore( );
}

[我大量使用GRPC route_guide_client.cc作为指导来帮助我编写上述应用程序。

我已经尝试将调用添加到grpc_init( )grpc_shutdown( ),即使它们的客户端示例都不包含任何调用。但是添加这些没有效果。

我在这里想念什么(如果有的话?我是否忘了调用/填充框架在应用程序退出时试图清除的内容?

c++ c++17 visual-studio-2019 grpc access-violation
1个回答
0
投票

好的,我相信我已经找到了造成此问题的原因。

在我的原始帖子中,我说:

即使在grpc_init( )grpc_shutdown( )中,我都尝试添加了呼叫客户示例不包含任何调用。但添加这些无效。“

是的,但是在重新阅读了grpc_shutdown( )的文档后,我注意到了这一点(强调我的意思:)>

最后一次调用grpc_shutdown将启动清理grpc库内部,可能发生在另一个线程中。一旦清理完成,grpc不使用任何内存,也没有任何指令在grpc库中执行。 在致电之前,所有申请拥有的grpc对象必须已销毁。

这是我认为我做错了的地方。我仍然在作用域中有grpc对象时正在调用grpc_shutdown()。为了更正,我确定了grpc objects的范围,然后在退出该范围时调用了grpc_shutdown()。这似乎已解决了问题。

New Grpc Client

int main( )
{
    std::cout << "Press enter\n";
    std::cin.ignore( );

    std::cout << "Calling Grpc service\n";
    grpc_init( );

    { // <- Intentionally added scope here.

        grpc::SslCredentialsOptions options;

        if ( auto certificate{ ReadCertificate( ) } )
            options.pem_root_certs = std::move( certificate ).value( );
        else return 1;

        auto credentials{ grpc::SslCredentials( options ) };
        auto channel{ grpc::CreateChannel( "localhost:5001", credentials ) };
        auto stub{ MeterReadingService::NewStub( channel ) };

        std::cout << "Sending single packet\n";
        SendPacket( stub.get( ), 8000 );

        std::cout << "Sending multiple packets\n";
        StreamDiagnostics( stub.get( ), 3 );
    }

    std::cout << "Shutting down library\n";
    grpc_shutdown_blocking( );
    std::cout << "Shut down complete press enter to exit\n";
    std::cin.ignore( );
}
© www.soinside.com 2019 - 2024. All rights reserved.