Index: lldb/include/lldb/Core/Communication.h =================================================================== --- lldb/include/lldb/Core/Communication.h +++ lldb/include/lldb/Core/Communication.h @@ -209,6 +209,22 @@ size_t Write(const void *src, size_t src_len, lldb::ConnectionStatus &status, Status *error_ptr); + /// Repeatedly attempt writing until either \a src_len bytes are written + /// or a permanent failure occurs. + /// + /// \param[in] src + /// A source buffer that must be at least \a src_len bytes + /// long. + /// + /// \param[in] src_len + /// The number of bytes to attempt to write, and also the + /// number of bytes are currently available in \a src. + /// + /// \return + /// The number of bytes actually Written. + size_t WriteAll(const void *src, size_t src_len, + lldb::ConnectionStatus &status, Status *error_ptr); + /// Sets the connection that it to be used by this class. /// /// By making a communication class that uses different connections it Index: lldb/source/Core/Communication.cpp =================================================================== --- lldb/source/Core/Communication.cpp +++ lldb/source/Core/Communication.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -189,6 +190,23 @@ return 0; } +size_t Communication::WriteAll(const void *src, size_t src_len, + ConnectionStatus &status, Status *error_ptr) { + size_t total_written = 0; + while (1) { + size_t written = Write(static_cast(src) + total_written, + src_len - total_written, status, error_ptr); + total_written += written; + if (status != eConnectionStatusSuccess || total_written >= src_len) + break; + // sleep a short while to avoid wasting CPU cycles while we are unlikely + // to be able to write again immediately + // FIXME: improve this to use select() + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + return total_written; +} + bool Communication::StartReadThread(Status *error_ptr) { if (error_ptr) error_ptr->Clear(); Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -101,7 +101,7 @@ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); ConnectionStatus status = eConnectionStatusSuccess; char ch = '+'; - const size_t bytes_written = Write(&ch, 1, status, nullptr); + const size_t bytes_written = WriteAll(&ch, 1, status, nullptr); LLDB_LOGF(log, "<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); m_history.AddPacket(ch, GDBRemotePacket::ePacketTypeSend, bytes_written); return bytes_written; @@ -111,7 +111,7 @@ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); ConnectionStatus status = eConnectionStatusSuccess; char ch = '-'; - const size_t bytes_written = Write(&ch, 1, status, nullptr); + const size_t bytes_written = WriteAll(&ch, 1, status, nullptr); LLDB_LOGF(log, "<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); m_history.AddPacket(ch, GDBRemotePacket::ePacketTypeSend, bytes_written); return bytes_written; @@ -137,7 +137,7 @@ ConnectionStatus status = eConnectionStatusSuccess; const char *packet_data = packet.data(); const size_t packet_length = packet.size(); - size_t bytes_written = Write(packet_data, packet_length, status, nullptr); + size_t bytes_written = WriteAll(packet_data, packet_length, status, nullptr); if (log) { size_t binary_start_offset = 0; if (strncmp(packet_data, "$vFile:pwrite:", strlen("$vFile:pwrite:")) ==