Grp c нарушение доступа на клиенте - PullRequest
0 голосов
/ 25 марта 2020

Я в процессе возни с GRPC. В настоящее время я использую C# веб-приложение в качестве моего 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

GRP C Клиент

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( ), хотя их клиентские примеры не Не содержит ни звонков. Но добавление их не имело никакого эффекта.

Что (если вообще что-то) мне здесь не хватает? Я забыл вызвать / заполнить что-то, что фреймворк пытается очистить при выходе из приложения?

1 Ответ

0 голосов
/ 26 марта 2020

ОК. Кажется, я нашел причину проблемы.

В своем исходном сообщении я сказал:

Я пытался добавить вызовы к grpc_init( ) и grpc_shutdown( ), хотя примеры клиентов не содержат ни вызовов. Но добавление тех не имело никакого эффекта. "

Это было правдой, но после перечитывания документации для grpc_shutdown( ) я заметил это (выделение мое):

последний вызов grpc_shutdown инициирует очистку внутренних компонентов библиотеки grpc, что может произойти в другом потоке. После завершения очистки grp c не использует память, и никакие инструкции не выполняются в рамках grp * 1031. * library. Перед вызовом все объекты grp c, принадлежащие приложению, должны быть уничтожены.

Здесь я думаю, что я ошибся. Я звонил grpc_shutdown() в то время как у меня все еще были объекты grp c в области видимости. Чтобы исправить, я определил область действия grp c objects и затем вызвал grpc_shutdown(), как только эта область была закрыта. Это, кажется, исправило проблему.

Новый Grp c Клиент

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( );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...