asked it to simplify the code
Test And Build / Lint (push) Successful in 5s
Test And Build / Build (push) Failing after 8s

This commit is contained in:
2026-08-07 15:54:45 +02:00
parent 1aeff55111
commit 4d61d0177a
3 changed files with 72 additions and 78 deletions
+59 -75
View File
@@ -75,7 +75,6 @@ the higher level `turboPmac` driver to manually call the `pmacFlush` function.
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <osiSock.h>
#include <osiUnistd.h>
#include <stdexcept>
#include <string>
#include <sys/poll.h>
@@ -124,13 +123,11 @@ constexpr double SEND_RETRY_DELAY = 0.01;
*/
static int setNonBlock(SOCKET fd, int nonBlockFlag) {
#if defined(vxWorks)
int flags;
flags = nonBlockFlag;
int flags = nonBlockFlag;
if (ioctl(fd, FIONBIO, (int)&flags) < 0)
return -1;
#elif defined(_WIN32)
unsigned long int flags;
flags = nonBlockFlag;
unsigned long int flags = nonBlockFlag;
if (socket_ioctl(fd, FIONBIO, &flags) < 0)
return -1;
#else
@@ -148,10 +145,9 @@ static int setNonBlock(SOCKET fd, int nonBlockFlag) {
}
pmacAsynIPPort::pmacAsynIPPort(const char *portName, const char *hostInfo)
: asynPortDriver(
portName, 1 /* maxAddr */, asynOctetMask | asynInt32Mask,
0 /* interruptMask */, ASYN_CANBLOCK, 1 /* autoConnect */,
0 /* priority */, 0 /* stackSize */),
: asynPortDriver(portName, 1 /* maxAddr */, asynOctetMask | asynInt32Mask,
0 /* interruptMask */, ASYN_CANBLOCK, 1 /* autoConnect */,
0 /* priority */, 0 /* stackSize */),
inBuf_(MAX_BUFFER_SIZE) {
// The base class constructor mirrors drvAsynIPPortConfigure(portName,
// hostInfo, priority, noAutoConnect) with ASYN_CANBLOCK and autoConnect
@@ -196,7 +192,7 @@ void pmacAsynIPPort::parseHostInfo(const char *hostInfo) {
asynStatus pmacAsynIPPort::connectIt(asynUser *pasynUser) {
SOCKET fd;
int i;
int i = 1;
char sockerrmsg[256];
osiSockAddr farAddr;
@@ -237,15 +233,14 @@ asynStatus pmacAsynIPPort::connectIt(asynUser *pasynUser) {
if (setNonBlock(fd, 1) < 0) {
epicsSocketConvertErrnoToString(sockerrmsg, sizeof(sockerrmsg));
epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
"Can't set %s O_NONBLOCK option: %s",
IPHostName_.c_str(), sockerrmsg);
"Can't set %s O_NONBLOCK option: %s", IPHostName_.c_str(),
sockerrmsg);
epicsSocketDestroy(fd);
return asynError;
}
{
int connectResult =
::connect(fd, &farAddr.sa, sizeof(farAddr.ia));
int connectResult = ::connect(fd, &farAddr.sa, sizeof(farAddr.ia));
if (connectResult < 0 &&
(SOCKERRNO == SOCK_EWOULDBLOCK || SOCKERRNO == SOCK_EINPROGRESS)) {
int msConnectTimeout;
@@ -285,7 +280,6 @@ asynStatus pmacAsynIPPort::connectIt(asynUser *pasynUser) {
}
}
i = 1;
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&i, sizeof i) < 0) {
epicsSocketConvertErrnoToString(sockerrmsg, sizeof(sockerrmsg));
epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
@@ -336,14 +330,37 @@ asynStatus pmacAsynIPPort::disconnect(asynUser *pasynUser) {
return asynSuccess;
}
asynStatus pmacAsynIPPort::pollSocket(asynUser *pasynUser,
struct pollfd *pollfd, int pollmsec,
int *pollstatus) {
epicsTimeStamp startTime;
epicsTimeStamp endTime;
epicsTimeGetCurrent(&startTime);
while ((*pollstatus = poll(pollfd, 1, pollmsec)) < 0) {
if (SOCKERRNO != SOCK_EINTR) {
char sockerrmsg[256];
epicsSocketConvertErrnoToString(sockerrmsg, sizeof(sockerrmsg));
epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
"%s poll() failed: %s", IPHostName_.c_str(),
sockerrmsg);
return asynError;
}
epicsTimeGetCurrent(&endTime);
if (epicsTimeDiffInSeconds(&endTime, &startTime) * 1000. > pollmsec)
break;
}
return asynSuccess;
}
asynStatus pmacAsynIPPort::socketRead(asynUser *pasynUser, char *data,
size_t maxchars, size_t *nbytesRead) {
int thisRead;
int readPollmsec;
int pollstatus;
asynStatus status = asynSuccess;
char sockerrmsg[256];
epicsTimeStamp startTime;
epicsTimeStamp endTime;
struct pollfd pollfd;
*nbytesRead = 0;
if (fd_ == INVALID_SOCKET) {
@@ -363,25 +380,11 @@ asynStatus pmacAsynIPPort::socketRead(asynUser *pasynUser, char *data,
if (readPollmsec < 0)
readPollmsec = -1;
{
struct pollfd pollfd;
pollfd.fd = fd_;
pollfd.events = POLLIN;
epicsTimeGetCurrent(&startTime);
while (poll(&pollfd, 1, readPollmsec) < 0) {
if (SOCKERRNO != SOCK_EINTR) {
epicsSocketConvertErrnoToString(sockerrmsg, sizeof(sockerrmsg));
epicsSnprintf(pasynUser->errorMessage,
pasynUser->errorMessageSize, "Poll() failed: %s",
sockerrmsg);
return asynError;
}
epicsTimeGetCurrent(&endTime);
if (epicsTimeDiffInSeconds(&endTime, &startTime) * 1000. >
readPollmsec)
break;
}
}
pollfd.fd = fd_;
pollfd.events = POLLIN;
status = pollSocket(pasynUser, &pollfd, readPollmsec, &pollstatus);
if (status != asynSuccess)
return status;
thisRead = recv(fd_, data, (int)maxchars, 0);
if (thisRead < 0) {
@@ -419,10 +422,12 @@ asynStatus pmacAsynIPPort::socketWrite(asynUser *pasynUser, const char *data,
asynStatus status = asynSuccess;
int thisWrite;
int writePollmsec;
int pollstatus;
epicsTimeStamp startTime;
epicsTimeStamp endTime;
int haveStartTime = 0;
char sockerrmsg[256];
struct pollfd pollfd;
asynPrint(pasynUser, ASYN_TRACE_FLOW, "%s write.\n", IPHostName_.c_str());
*nbytesTransferred = 0;
@@ -439,25 +444,11 @@ asynStatus pmacAsynIPPort::socketWrite(asynUser *pasynUser, const char *data,
if (writePollmsec < 0)
writePollmsec = -1;
for (;;) {
int pollstatus;
struct pollfd pollfd;
pollfd.fd = fd_;
pollfd.events = POLLOUT;
epicsTimeGetCurrent(&startTime);
while ((pollstatus = poll(&pollfd, 1, writePollmsec)) < 0) {
if (SOCKERRNO != SOCK_EINTR) {
epicsSocketConvertErrnoToString(sockerrmsg, sizeof(sockerrmsg));
epicsSnprintf(pasynUser->errorMessage,
pasynUser->errorMessageSize,
"%s poll() failed: %s", IPHostName_.c_str(),
sockerrmsg);
return asynError;
}
epicsTimeGetCurrent(&endTime);
if (epicsTimeDiffInSeconds(&endTime, &startTime) * 1000 >
writePollmsec)
break;
}
status = pollSocket(pasynUser, &pollfd, writePollmsec, &pollstatus);
if (status != asynSuccess)
return status;
if (pollstatus == 0) {
epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize,
"%s poll() timed out", IPHostName_.c_str());
@@ -504,8 +495,7 @@ asynStatus pmacAsynIPPort::socketWrite(asynUser *pasynUser, const char *data,
break;
}
}
asynPrint(pasynUser, ASYN_TRACE_FLOW,
"wrote %lu to %s, return %s.\n",
asynPrint(pasynUser, ASYN_TRACE_FLOW, "wrote %lu to %s, return %s.\n",
(unsigned long)*nbytesTransferred, IPHostName_.c_str(),
pasynManager->strStatus(status));
return status;
@@ -700,9 +690,9 @@ asynStatus pmacAsynIPPort::writeOctet(asynUser *pasynUser, const char *data,
poutCmd_.wValue = data[0];
poutCmd_.wIndex = 0;
poutCmd_.wLength = htons(0);
status = socketWrite(pasynUser,
reinterpret_cast<const char *>(&poutCmd_),
ETHERNET_CMD_HEADER, &nbytesActual);
status =
socketWrite(pasynUser, reinterpret_cast<const char *>(&poutCmd_),
ETHERNET_CMD_HEADER, &nbytesActual);
*nbytesTransfered = nbytesActual == ETHERNET_CMD_HEADER ? numchars : 0;
} else {
if (numchars > ETHERNET_DATA_SIZE) {
@@ -743,9 +733,9 @@ asynStatus pmacAsynIPPort::writeOctet(asynUser *pasynUser, const char *data,
poutCmd_.wIndex = 0;
poutCmd_.wLength = htons(numchars);
memcpy(poutCmd_.bData, data, numchars);
status = socketWrite(pasynUser,
reinterpret_cast<const char *>(&poutCmd_),
numchars + ETHERNET_CMD_HEADER, &nbytesActual);
status =
socketWrite(pasynUser, reinterpret_cast<const char *>(&poutCmd_),
numchars + ETHERNET_CMD_HEADER, &nbytesActual);
if (nbytesActual > ETHERNET_CMD_HEADER)
*nbytesTransfered = nbytesActual - ETHERNET_CMD_HEADER;
else
@@ -833,8 +823,8 @@ asynStatus pmacAsynIPPort::readOctet(asynUser *pasynUser, char *data,
nbytesTransfered);
}
}
status = readResponse(pasynUser, maxchars - nRead, &thisRead,
eomReason);
status =
readResponse(pasynUser, maxchars - nRead, &thisRead, eomReason);
initialRead = false;
if (status != asynSuccess || thisRead == 0)
break;
@@ -880,19 +870,13 @@ asynStatus pmacAsynIPPort::flushOctet(asynUser *pasynUser) {
asynStatus pmacAsynIPPort::writeInt32(asynUser *pasynUser, epicsInt32 value) {
asynPrint(pasynUser, ASYN_TRACE_FLOW, "pmacAsynIPPort::writeInt32\n");
if (pasynUser->reason == FLUSH_HARDWARE) {
/*
According to the Turbo PMAC user manual, p. 414:
0 - failed 1 - success
*/
if (pmacFlush(pasynUser) == 1) {
return asynSuccess;
} else {
return asynError;
}
} else {
if (pasynUser->reason != FLUSH_HARDWARE)
return asynPortDriver::writeInt32(pasynUser, value);
}
/* Turbo PMAC User Manual, p. 414: 0 - failed, 1 - success */
if (pmacFlush(pasynUser) == 1)
return asynSuccess;
return asynError;
}
// =============================================================================
+10
View File
@@ -120,6 +120,16 @@ class HIDDEN pmacAsynIPPort : public asynPortDriver {
asynStatus socketWrite(asynUser *pasynUser, const char *data,
size_t numchars, size_t *nbytesWritten);
/**
* @brief Poll the socket fd, retrying while poll() is interrupted by
* EINTR.
*
* @return asynSuccess with *pollstatus holding poll()'s return value, or
* asynError if poll() failed for a different reason.
*/
asynStatus pollSocket(asynUser *pasynUser, struct pollfd *pollfd,
int pollmsec, int *pollstatus);
/**
* @brief Read response data from the PMAC into the internal input buffer
*
+3 -3
View File
@@ -36,8 +36,6 @@ struct turboPmacControllerImpl {
// Timeout for the communication process in seconds
double comTimeout;
char lastResponse[sinqController::MAXBUF_];
// User for writing int32 values to the port driver.
asynUser *pasynInt32SyncIOipPort;
@@ -46,6 +44,8 @@ struct turboPmacControllerImpl {
int readConfig;
int flushHardware;
int limFromHardware;
char lastResponse[sinqController::MAXBUF_];
};
#define NUM_turboPmac_DRIVER_PARAMS 5
@@ -65,12 +65,12 @@ turboPmacController::turboPmacController(const char *portName,
pTurboPmacC_(
std::make_unique<turboPmacControllerImpl>((turboPmacControllerImpl){
.comTimeout = comTimeout,
.lastResponse = {0},
.pasynInt32SyncIOipPort = nullptr, // Populated in constructor
.rereadEncoderPosition = 0, // Populated in constructor
.readConfig = 0, // Populated in constructor
.flushHardware = 0, // Populated in constructor
.limFromHardware = 0, // Populated in constructor
.lastResponse = {0},
})) {
// Initialization of local variables
asynStatus status = asynSuccess;