Skip to content

Commit

Permalink
hackAroundRTEMSSocketInterrupt
Browse files Browse the repository at this point in the history
  • Loading branch information
mdavidsaver committed Nov 22, 2020
1 parent 9423252 commit d005260
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/remote/blockingTCPAcceptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ void BlockingTCPAcceptor::destroy() {
{
case esscimqi_socketBothShutdownRequired:
shutdown(sock, SHUT_RDWR);
hackAroundRTEMSSocketInterrupt();
epicsSocketDestroy(sock);
_thread.exitWait();
break;
Expand Down
1 change: 1 addition & 0 deletions src/remote/blockingUDPTransport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ void BlockingUDPTransport::close(bool waitForThreadToComplete) {
case esscimqi_socketBothShutdownRequired:
{
/*int status =*/ ::shutdown ( _channel, SHUT_RDWR );
hackAroundRTEMSSocketInterrupt();
/*
if ( status ) {
char sockErrBuf[64];
Expand Down
24 changes: 24 additions & 0 deletions src/remote/codec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,29 @@ struct BreakTransport : TransportSender
namespace epics {
namespace pvAccess {

/* HACK!
* RTEMS allows blocking sockets to be interrupted by shutdown() (aka. esscimqi_socketBothShutdownRequired).
* However, a concurrent close() is a race which can leave a send()/recv() call permanently stuck!
* The _right_ way to handle this (aside from fixing the stack) would be to sequence
* shutdown() -> exitWait() -> destroy()
* This is hard to handle since this must be done for _both_ sender and receiver thread,
* which presents difficulties owing to how the Transport hierarchy since Transport::close()
* can happen on either worker, or a user thread.
* Rather than try to straighten this mess out properly, we add this "wait" in-between
* shutdown() and close() to hopefully wait for the workers (or other worker) to return
* from send()/recv().
*/
void hackAroundRTEMSSocketInterrupt()
{
#ifdef __rtems__
epicsThreadId self = epicsThreadGetIdSelf();
unsigned orig = epicsThreadGetPrioritySelf();
epicsThreadSetPriority(self, epicsThreadPriorityMin);
epicsThreadSleep(0.0000001);
epicsThreadSetPriority(self, orig);
#endif
}

size_t Transport::num_instances;

Transport::Transport()
Expand Down Expand Up @@ -1031,6 +1054,7 @@ void BlockingTCPTransportCodec::internalClose()
case esscimqi_socketBothShutdownRequired:
{
/*int status =*/ ::shutdown ( _channel, SHUT_RDWR );
hackAroundRTEMSSocketInterrupt();
/*
if ( status ) {
char sockErrBuf[64];
Expand Down
2 changes: 2 additions & 0 deletions src/remote/pv/remote.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ enum ControlCommands {
CMD_SET_ENDIANESS = 2
};

void hackAroundRTEMSSocketInterrupt();

/**
* Interface defining transport send control.
*/
Expand Down

0 comments on commit d005260

Please sign in to comment.