Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "Add Reverse Diagnostics Server" #35767

Merged
merged 1 commit into from
May 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
277 changes: 43 additions & 234 deletions src/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,13 @@
#include "diagnosticsipc.h"
#include "processdescriptor.h"

#if __GNUC__
#include <poll.h>
#else
#include <sys/poll.h>
#endif // __GNUC__

IpcStream::DiagnosticsIpc::DiagnosticsIpc(const int serverSocket, sockaddr_un *const pServerAddress, ConnectionMode mode) :
mode(mode),
IpcStream::DiagnosticsIpc::DiagnosticsIpc(const int serverSocket, sockaddr_un *const pServerAddress) :
_serverSocket(serverSocket),
_pServerAddress(new sockaddr_un),
_isClosed(false),
_isListening(false)
_isClosed(false)
{
_ASSERTE(_pServerAddress != nullptr);
_ASSERTE(_serverSocket != -1);
_ASSERTE(pServerAddress != nullptr);

if (_pServerAddress == nullptr || pServerAddress == nullptr)
Expand All @@ -39,8 +32,24 @@ IpcStream::DiagnosticsIpc::~DiagnosticsIpc()
delete _pServerAddress;
}

IpcStream::DiagnosticsIpc *IpcStream::DiagnosticsIpc::Create(const char *const pIpcName, ConnectionMode mode, ErrorCallback callback)
IpcStream::DiagnosticsIpc *IpcStream::DiagnosticsIpc::Create(const char *const pIpcName, ErrorCallback callback)
{
#ifdef __APPLE__
mode_t prev_mask = umask(~(S_IRUSR | S_IWUSR)); // This will set the default permission bit to 600
#endif // __APPLE__

const int serverSocket = ::socket(AF_UNIX, SOCK_STREAM, 0);
if (serverSocket == -1)
{
if (callback != nullptr)
callback(strerror(errno), errno);
#ifdef __APPLE__
umask(prev_mask);
#endif // __APPLE__
_ASSERTE(!"Failed to create diagnostics IPC socket.");
return nullptr;
}

sockaddr_un serverAddress{};
serverAddress.sun_family = AF_UNIX;

Expand All @@ -62,24 +71,6 @@ IpcStream::DiagnosticsIpc *IpcStream::DiagnosticsIpc::Create(const char *const p
"socket");
}

if (mode == ConnectionMode::CLIENT)
return new IpcStream::DiagnosticsIpc(-1, &serverAddress, ConnectionMode::CLIENT);

#ifdef __APPLE__
mode_t prev_mask = umask(~(S_IRUSR | S_IWUSR)); // This will set the default permission bit to 600
#endif // __APPLE__

const int serverSocket = ::socket(AF_UNIX, SOCK_STREAM, 0);
if (serverSocket == -1)
{
if (callback != nullptr)
callback(strerror(errno), errno);
#ifdef __APPLE__
umask(prev_mask);
#endif // __APPLE__
_ASSERTE(!"Failed to create diagnostics IPC socket.");
return nullptr;
}

#ifndef __APPLE__
if (fchmod(serverSocket, S_IRUSR | S_IWUSR) == -1)
Expand Down Expand Up @@ -108,52 +99,33 @@ IpcStream::DiagnosticsIpc *IpcStream::DiagnosticsIpc::Create(const char *const p
return nullptr;
}

#ifdef __APPLE__
umask(prev_mask);
#endif // __APPLE__

return new IpcStream::DiagnosticsIpc(serverSocket, &serverAddress, mode);
}

bool IpcStream::DiagnosticsIpc::Listen(ErrorCallback callback)
{
_ASSERTE(mode == ConnectionMode::SERVER);
if (mode != ConnectionMode::SERVER)
{
if (callback != nullptr)
callback("Cannot call Listen on a client connection", -1);
return false;
}

if (_isListening)
return true;

const int fSuccessfulListen = ::listen(_serverSocket, /* backlog */ 255);
const int fSuccessfulListen = ::listen(serverSocket, /* backlog */ 255);
if (fSuccessfulListen == -1)
{
if (callback != nullptr)
callback(strerror(errno), errno);
_ASSERTE(fSuccessfulListen != -1);

const int fSuccessUnlink = ::unlink(_pServerAddress->sun_path);
const int fSuccessUnlink = ::unlink(serverAddress.sun_path);
_ASSERTE(fSuccessUnlink != -1);

const int fSuccessClose = ::close(_serverSocket);
const int fSuccessClose = ::close(serverSocket);
_ASSERTE(fSuccessClose != -1);
return false;
}
else
{
_isListening = true;
return true;
#ifdef __APPLE__
umask(prev_mask);
#endif // __APPLE__
return nullptr;
}

#ifdef __APPLE__
umask(prev_mask);
#endif // __APPLE__

return new IpcStream::DiagnosticsIpc(serverSocket, &serverAddress);
}

IpcStream *IpcStream::DiagnosticsIpc::Accept(ErrorCallback callback)
IpcStream *IpcStream::DiagnosticsIpc::Accept(ErrorCallback callback) const
{
_ASSERTE(mode == ConnectionMode::SERVER);
_ASSERTE(_isListening);

sockaddr_un from;
socklen_t fromlen = sizeof(from);
const int clientSocket = ::accept(_serverSocket, (sockaddr *)&from, &fromlen);
Expand All @@ -164,114 +136,7 @@ IpcStream *IpcStream::DiagnosticsIpc::Accept(ErrorCallback callback)
return nullptr;
}

return new IpcStream(clientSocket, mode);
}

IpcStream *IpcStream::DiagnosticsIpc::Connect(ErrorCallback callback)
{
_ASSERTE(mode == ConnectionMode::CLIENT);

sockaddr_un clientAddress{};
clientAddress.sun_family = AF_UNIX;
const int clientSocket = ::socket(AF_UNIX, SOCK_STREAM, 0);
if (clientSocket == -1)
{
if (callback != nullptr)
callback(strerror(errno), errno);
return nullptr;
}

// We don't expect this to block since this is a Unix Domain Socket. `connect` may block until the
// TCP handshake is complete for TCP/IP sockets, but UDS don't use TCP. `connect` will return even if
// the server hasn't called `accept`.
if (::connect(clientSocket, (struct sockaddr *)_pServerAddress, sizeof(*_pServerAddress)) < 0)
{
if (callback != nullptr)
callback(strerror(errno), errno);
return nullptr;
}

return new IpcStream(clientSocket, ConnectionMode::CLIENT);
}

int32_t IpcStream::DiagnosticsIpc::Poll(IpcPollHandle *rgIpcPollHandles, uint32_t nHandles, int32_t timeoutMs, ErrorCallback callback)
{
// prepare the pollfd structs
pollfd *pollfds = new pollfd[nHandles];
for (uint32_t i = 0; i < nHandles; i++)
{
rgIpcPollHandles[i].revents = 0; // ignore any values in revents
int fd = -1;
if (rgIpcPollHandles[i].pIpc != nullptr)
{
// SERVER
_ASSERTE(rgIpcPollHandles[i].pIpc->mode == ConnectionMode::SERVER);
fd = rgIpcPollHandles[i].pIpc->_serverSocket;
}
else
{
// CLIENT
_ASSERTE(rgIpcPollHandles[i].pStream != nullptr);
fd = rgIpcPollHandles[i].pStream->_clientSocket;
}

pollfds[i].fd = fd;
pollfds[i].events = POLLIN;
}

int retval = poll(pollfds, nHandles, timeoutMs);

// Check results
if (retval < 0)
{
for (uint32_t i = 0; i < nHandles; i++)
{
if ((pollfds[i].revents & POLLERR) && callback != nullptr)
callback(strerror(errno), errno);
rgIpcPollHandles[i].revents = (uint8_t)PollEvents::ERR;
}
delete[] pollfds;
return -1;
}
else if (retval == 0)
{
// we timed out
delete[] pollfds;
return 0;
}

for (uint32_t i = 0; i < nHandles; i++)
{
if (pollfds[i].revents != 0)
{
// error check FIRST
if (pollfds[i].revents & POLLHUP)
{
// check for hangup first because a closed socket
// will technically meet the requirements for POLLIN
// i.e., a call to recv/read won't block
rgIpcPollHandles[i].revents = (uint8_t)PollEvents::HANGUP;
delete[] pollfds;
return -1;
}
else if ((pollfds[i].revents & (POLLERR|POLLNVAL)))
{
if (callback != nullptr)
callback("Poll error", (uint32_t)pollfds[i].revents);
rgIpcPollHandles[i].revents = (uint8_t)PollEvents::ERR;
delete[] pollfds;
return -1;
}
else if (pollfds[i].revents & POLLIN)
{
rgIpcPollHandles[i].revents = (uint8_t)PollEvents::SIGNALED;
break;
}
}
}

delete[] pollfds;
return 1;
return new IpcStream(clientSocket);
}

void IpcStream::DiagnosticsIpc::Close(ErrorCallback callback)
Expand Down Expand Up @@ -307,101 +172,45 @@ void IpcStream::DiagnosticsIpc::Unlink(ErrorCallback callback)
}

IpcStream::~IpcStream()
{
Close();
}

void IpcStream::Close(ErrorCallback)
{
if (_clientSocket != -1)
{
Flush();

const int fSuccessClose = ::close(_clientSocket);
_ASSERTE(fSuccessClose != -1);
_clientSocket = -1;
}
}

bool IpcStream::Read(void *lpBuffer, const uint32_t nBytesToRead, uint32_t &nBytesRead, const int32_t timeoutMs)
bool IpcStream::Read(void *lpBuffer, const uint32_t nBytesToRead, uint32_t &nBytesRead) const
{
_ASSERTE(lpBuffer != nullptr);

if (timeoutMs != InfiniteTimeout)
{
pollfd pfd;
pfd.fd = _clientSocket;
pfd.events = POLLIN;
int retval = poll(&pfd, 1, timeoutMs);
if (retval <= 0 || pfd.revents != POLLIN)
{
// timeout or error
return false;
}
// else fallthrough
}

uint8_t *lpBufferCursor = (uint8_t*)lpBuffer;
ssize_t currentBytesRead = 0;
ssize_t totalBytesRead = 0;
bool fSuccess = true;
while (fSuccess && nBytesToRead - totalBytesRead > 0)
{
currentBytesRead = ::recv(_clientSocket, lpBufferCursor, nBytesToRead - totalBytesRead, 0);
fSuccess = currentBytesRead != 0;
if (!fSuccess)
break;
totalBytesRead += currentBytesRead;
lpBufferCursor += currentBytesRead;
}
const ssize_t ssize = ::recv(_clientSocket, lpBuffer, nBytesToRead, 0);
const bool fSuccess = ssize != -1;

if (!fSuccess)
{
// TODO: Add error handling.
}

nBytesRead = static_cast<uint32_t>(totalBytesRead);
nBytesRead = static_cast<uint32_t>(ssize);
return fSuccess;
}

bool IpcStream::Write(const void *lpBuffer, const uint32_t nBytesToWrite, uint32_t &nBytesWritten, const int32_t timeoutMs)
bool IpcStream::Write(const void *lpBuffer, const uint32_t nBytesToWrite, uint32_t &nBytesWritten) const
{
_ASSERTE(lpBuffer != nullptr);

if (timeoutMs != InfiniteTimeout)
{
pollfd pfd;
pfd.fd = _clientSocket;
pfd.events = POLLOUT;
int retval = poll(&pfd, 1, timeoutMs);
if (retval <= 0 || pfd.revents != POLLOUT)
{
// timeout or error
return false;
}
// else fallthrough
}

uint8_t *lpBufferCursor = (uint8_t*)lpBuffer;
ssize_t currentBytesWritten = 0;
ssize_t totalBytesWritten = 0;
bool fSuccess = true;
while (fSuccess && nBytesToWrite - totalBytesWritten > 0)
{
currentBytesWritten = ::send(_clientSocket, lpBufferCursor, nBytesToWrite - totalBytesWritten, 0);
fSuccess = currentBytesWritten != -1;
if (!fSuccess)
break;
lpBufferCursor += currentBytesWritten;
totalBytesWritten += currentBytesWritten;
}
const ssize_t ssize = ::send(_clientSocket, lpBuffer, nBytesToWrite, 0);
const bool fSuccess = ssize != -1;

if (!fSuccess)
{
// TODO: Add error handling.
}

nBytesWritten = static_cast<uint32_t>(totalBytesWritten);
nBytesWritten = static_cast<uint32_t>(ssize);
return fSuccess;
}

Expand Down
Loading