Skip to content

Commit 5c29e14

Browse files
John Salemnoahfalk
andauthored
[test] fix hang in macOS variants of reverse diagnostics server tests (#40225)
Co-authored-by: Noah Falk <noahfalk@users.noreply.github.com>
1 parent 05e2cfb commit 5c29e14

7 files changed

Lines changed: 66 additions & 27 deletions

File tree

src/coreclr/src/debug/debug-pal/unix/diagnosticsipc.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -246,28 +246,31 @@ int32_t IpcStream::DiagnosticsIpc::Poll(IpcPollHandle *rgIpcPollHandles, uint32_
246246
{
247247
if (pollfds[i].revents != 0)
248248
{
249+
if (callback != nullptr)
250+
callback("IpcStream::DiagnosticsIpc::Poll - poll revents", (uint32_t)pollfds[i].revents);
249251
// error check FIRST
250252
if (pollfds[i].revents & POLLHUP)
251253
{
252254
// check for hangup first because a closed socket
253255
// will technically meet the requirements for POLLIN
254256
// i.e., a call to recv/read won't block
255257
rgIpcPollHandles[i].revents = (uint8_t)PollEvents::HANGUP;
256-
delete[] pollfds;
257-
return -1;
258258
}
259259
else if ((pollfds[i].revents & (POLLERR|POLLNVAL)))
260260
{
261261
if (callback != nullptr)
262262
callback("Poll error", (uint32_t)pollfds[i].revents);
263263
rgIpcPollHandles[i].revents = (uint8_t)PollEvents::ERR;
264-
delete[] pollfds;
265-
return -1;
266264
}
267265
else if (pollfds[i].revents & (POLLIN|POLLPRI))
268266
{
269267
rgIpcPollHandles[i].revents = (uint8_t)PollEvents::SIGNALED;
270-
break;
268+
}
269+
else
270+
{
271+
rgIpcPollHandles[i].revents = (uint8_t)PollEvents::UNKNOWN;
272+
if (callback != nullptr)
273+
callback("unkown poll response", (uint32_t)pollfds[i].revents);
271274
}
272275
}
273276
}
@@ -341,7 +344,7 @@ bool IpcStream::Read(void *lpBuffer, const uint32_t nBytesToRead, uint32_t &nByt
341344
pfd.fd = _clientSocket;
342345
pfd.events = POLLIN;
343346
int retval = poll(&pfd, 1, timeoutMs);
344-
if (retval <= 0 || pfd.revents != POLLIN)
347+
if (retval <= 0 || !(pfd.revents & POLLIN))
345348
{
346349
// timeout or error
347350
return false;
@@ -382,7 +385,7 @@ bool IpcStream::Write(const void *lpBuffer, const uint32_t nBytesToWrite, uint32
382385
pfd.fd = _clientSocket;
383386
pfd.events = POLLOUT;
384387
int retval = poll(&pfd, 1, timeoutMs);
385-
if (retval <= 0 || pfd.revents != POLLOUT)
388+
if (retval <= 0 || !(pfd.revents & POLLOUT))
386389
{
387390
// timeout or error
388391
return false;

src/coreclr/src/debug/inc/diagnosticsipc.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ typedef void (*ErrorCallback)(const char *szMessage, uint32_t code);
1616

1717
class IpcStream final
1818
{
19+
friend class IpcStreamFactory;
1920
public:
2021
static constexpr int32_t InfiniteTimeout = -1;
2122
~IpcStream();
@@ -26,6 +27,7 @@ class IpcStream final
2627

2728
class DiagnosticsIpc final
2829
{
30+
friend class IpcStreamFactory;
2931
public:
3032
enum ConnectionMode
3133
{
@@ -38,7 +40,8 @@ class IpcStream final
3840
NONE = 0x00, // no events
3941
SIGNALED = 0x01, // ready for use
4042
HANGUP = 0x02, // connection remotely closed
41-
ERR = 0x04 // other error
43+
ERR = 0x04, // error
44+
UNKNOWN = 0x80 // unknown state
4245
};
4346

4447
// The bookeeping struct used for polling on server and client structs
@@ -125,7 +128,7 @@ class IpcStream final
125128
private:
126129
#ifdef TARGET_UNIX
127130
int _clientSocket = -1;
128-
IpcStream(int clientSocket, int serverSocket, DiagnosticsIpc::ConnectionMode mode = DiagnosticsIpc::ConnectionMode::SERVER)
131+
IpcStream(int clientSocket, DiagnosticsIpc::ConnectionMode mode = DiagnosticsIpc::ConnectionMode::SERVER)
129132
: _clientSocket(clientSocket), _mode(mode) {}
130133
#else
131134
HANDLE _hPipe = INVALID_HANDLE_VALUE;

src/coreclr/src/vm/diagnosticserver.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ DWORD WINAPI DiagnosticServer::DiagnosticsServerThread(LPVOID)
7474
continue;
7575
}
7676

77+
STRESS_LOG2(LF_DIAGNOSTICS_PORT, LL_INFO10, "DiagnosticServer - received IPC message with command set (%d) and command id (%d)\n", message.GetHeader().CommandSet, message.GetHeader().CommandId);
78+
7779
switch ((DiagnosticsIpc::DiagnosticServerCommandSet)message.GetHeader().CommandSet)
7880
{
7981
case DiagnosticsIpc::DiagnosticServerCommandSet::EventPipe:

src/coreclr/src/vm/ipcstreamfactory.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ Volatile<bool> IpcStreamFactory::s_isShutdown = false;
1212

1313
bool IpcStreamFactory::ClientConnectionState::GetIpcPollHandle(IpcStream::DiagnosticsIpc::IpcPollHandle *pIpcPollHandle, ErrorCallback callback)
1414
{
15+
STRESS_LOG0(LF_DIAGNOSTICS_PORT, LL_INFO1000, "IpcStreamFactory::ClientConnectionState::GetIpcPollHandle - ENTER.\n");
1516
if (_pStream == nullptr)
1617
{
18+
STRESS_LOG0(LF_DIAGNOSTICS_PORT, LL_INFO10, "IpcStreamFactory::ClientConnectionState::GetIpcPollHandle - cache was empty!\n");
1719
// cache is empty, reconnect, e.g., there was a disconnect
1820
IpcStream *pConnection = _pIpc->Connect(callback);
1921
if (pConnection == nullptr)
@@ -22,6 +24,11 @@ bool IpcStreamFactory::ClientConnectionState::GetIpcPollHandle(IpcStream::Diagno
2224
callback("Failed to connect to client connection", -1);
2325
return false;
2426
}
27+
#ifdef TARGET_UNIX
28+
STRESS_LOG1(LF_DIAGNOSTICS_PORT, LL_INFO10, "IpcStreamFactory::ClientConnectionState::GetIpcPollHandle - returned connection { _clientSocket = %d }\n", pConnection->_clientSocket);
29+
#else
30+
STRESS_LOG2(LF_DIAGNOSTICS_PORT, LL_INFO10, "IpcStreamFactory::ClientConnectionState::GetIpcPollHandle - returned connection { _hPipe = %d, _oOverlap.hEvent = %d }\n", pConnection->_hPipe, pConnection->_oOverlap.hEvent);
31+
#endif
2532
if (!DiagnosticsIpc::SendIpcAdvertise_V1(pConnection))
2633
{
2734
if (callback != nullptr)
@@ -33,6 +40,7 @@ bool IpcStreamFactory::ClientConnectionState::GetIpcPollHandle(IpcStream::Diagno
3340
_pStream = pConnection;
3441
}
3542
*pIpcPollHandle = { nullptr, _pStream, 0, this };
43+
STRESS_LOG0(LF_DIAGNOSTICS_PORT, LL_INFO10, "IpcStreamFactory::ClientConnectionState::GetIpcPollHandle - EXIT.\n");
3644
return true;
3745
}
3846

@@ -139,6 +147,7 @@ int32_t IpcStreamFactory::GetNextTimeout(int32_t currentTimeoutMs)
139147

140148
IpcStream *IpcStreamFactory::GetNextAvailableStream(ErrorCallback callback)
141149
{
150+
STRESS_LOG0(LF_DIAGNOSTICS_PORT, LL_INFO10, "IpcStreamFactory::GetNextAvailableStream - ENTER");
142151
IpcStream *pStream = nullptr;
143152
CQuickArrayList<IpcStream::DiagnosticsIpc::IpcPollHandle> rgIpcPollHandles;
144153

@@ -168,6 +177,25 @@ IpcStream *IpcStreamFactory::GetNextAvailableStream(ErrorCallback callback)
168177

169178
nPollAttempts++;
170179
STRESS_LOG2(LF_DIAGNOSTICS_PORT, LL_INFO10, "IpcStreamFactory::GetNextAvailableStream - Poll attempt: %d, timeout: %dms.\n", nPollAttempts, pollTimeoutMs);
180+
for (uint32_t i = 0; i < rgIpcPollHandles.Size(); i++)
181+
{
182+
if (rgIpcPollHandles[i].pIpc != nullptr)
183+
{
184+
#ifdef TARGET_UNIX
185+
STRESS_LOG2(LF_DIAGNOSTICS_PORT, LL_INFO10, "\tSERVER IpcPollHandle[%d] = { _serverSocket = %d }\n", i, rgIpcPollHandles[i].pIpc->_serverSocket);
186+
#else
187+
STRESS_LOG3(LF_DIAGNOSTICS_PORT, LL_INFO10, "\tSERVER IpcPollHandle[%d] = { _hPipe = %d, _oOverlap.hEvent = %d }\n", i, rgIpcPollHandles[i].pIpc->_hPipe, rgIpcPollHandles[i].pIpc->_oOverlap.hEvent);
188+
#endif
189+
}
190+
else
191+
{
192+
#ifdef TARGET_UNIX
193+
STRESS_LOG2(LF_DIAGNOSTICS_PORT, LL_INFO10, "\tCLIENT IpcPollHandle[%d] = { _clientSocket = %d }\n", i, rgIpcPollHandles[i].pStream->_clientSocket);
194+
#else
195+
STRESS_LOG3(LF_DIAGNOSTICS_PORT, LL_INFO10, "\tCLIENT IpcPollHandle[%d] = { _hPipe = %d, _oOverlap.hEvent = %d }\n", i, rgIpcPollHandles[i].pStream->_hPipe, rgIpcPollHandles[i].pStream->_oOverlap.hEvent);
196+
#endif
197+
}
198+
}
171199
int32_t retval = IpcStream::DiagnosticsIpc::Poll(rgIpcPollHandles.Ptr(), (uint32_t)rgIpcPollHandles.Size(), pollTimeoutMs, callback);
172200
bool fSawError = false;
173201

@@ -211,6 +239,11 @@ IpcStream *IpcStreamFactory::GetNextAvailableStream(ErrorCallback callback)
211239
rgIpcPollHandles.Pop();
212240
}
213241

242+
#ifdef TARGET_UNIX
243+
STRESS_LOG2(LF_DIAGNOSTICS_PORT, LL_INFO10, "IpcStreamFactory::GetNextAvailableStream - EXIT :: Poll attempt: %d, stream using handle %d.\n", nPollAttempts, pStream->_clientSocket);
244+
#else
245+
STRESS_LOG2(LF_DIAGNOSTICS_PORT, LL_INFO10, "IpcStreamFactory::GetNextAvailableStream - EXIT :: Poll attempt: %d, stream using handle %d.\n", nPollAttempts, pStream->_hPipe);
246+
#endif
214247
return pStream;
215248
}
216249

src/tests/tracing/eventpipe/common/IpcUtils.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public static async Task<bool> RunSubprocess(Assembly currentAssembly, Dictionar
7070
foreach ((string key, string value) in environment)
7171
process.StartInfo.Environment.Add(key, value);
7272
process.StartInfo.FileName = Process.GetCurrentProcess().MainModule.FileName;
73-
process.StartInfo.Arguments = new Uri(currentAssembly.CodeBase).LocalPath + " 0";
73+
process.StartInfo.Arguments = new Uri(currentAssembly.Location).LocalPath + " 0";
7474
process.StartInfo.RedirectStandardOutput = true;
7575
process.StartInfo.RedirectStandardInput = true;
7676
process.StartInfo.RedirectStandardError = true;

src/tests/tracing/eventpipe/common/Reverse.cs

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ public ReverseServer(string serverAddress, int bufferSize = 16 * 1024)
102102
socket.ReceiveBufferSize = Math.Max(bufferSize, 128);
103103
socket.Bind(remoteEP);
104104
socket.Listen(255);
105-
socket.LingerState.Enabled = false;
106105
_server = socket;
107106
}
108107
}
@@ -166,20 +165,13 @@ public void Shutdown()
166165
}
167166
break;
168167
case Socket socket:
169-
try
170-
{
171-
socket.Shutdown(SocketShutdown.Both);
172-
}
173-
catch {}
174-
finally
175-
{
176-
_clientSocket?.Close();
177-
socket.Close();
178-
socket.Dispose();
179-
_clientSocket?.Dispose();
180-
if (File.Exists(_serverAddress))
181-
File.Delete(_serverAddress);
182-
}
168+
if (File.Exists(_serverAddress))
169+
File.Delete(_serverAddress);
170+
socket.Close();
171+
socket.Dispose();
172+
_clientSocket?.Shutdown(SocketShutdown.Both);
173+
_clientSocket?.Close();
174+
_clientSocket?.Dispose();
183175
break;
184176
default:
185177
throw new ArgumentException("Invalid server type");

src/tests/tracing/eventpipe/reverseouter/reverseouter.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,22 @@ public static async Task<bool> TEST_ReverseConnectionCanRecycleWhileTracing()
4747
Logger.logger.Log("Starting EventPipeSession over standard connection");
4848
using Stream stream = EventPipeClient.CollectTracing(pid, config, out var sessionId);
4949
Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:x}");
50-
using var source = new EventPipeEventSource(stream);
51-
Task readerTask = Task.Run(() => source.Process());
50+
// using var source = new EventPipeEventSource(stream);
51+
using var memroyStream = new MemoryStream();
52+
Task readerTask = stream.CopyToAsync(memroyStream);//Task.Run(() => source.Process());
5253
await Task.Delay(500);
5354
Logger.logger.Log("Stopping EventPipeSession over standard connection");
5455
EventPipeClient.StopTracing(pid, sessionId);
5556
await readerTask;
5657
Logger.logger.Log("Stopped EventPipeSession over standard connection");
5758
}
59+
catch (Exception e)
60+
{
61+
Logger.logger.Log(e.ToString());
62+
}
5863
finally
5964
{
65+
Logger.logger.Log("setting the MRE");
6066
mre.Set();
6167
}
6268
});

0 commit comments

Comments
 (0)