int wr = write(iob.fd, pkt, size);
if (wr == -1) {
if (errno == EPIPE) {
- delete this;
return false;
}
if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
// TODO log error
- delete this;
return false;
}
// EAGAIN etc: fall through to below
// We can't send out-of-memory response as we already wrote as much as we
// could above. Neither can we later send the response since we have currently
// sent an incomplete packet. All we can do is close the connection.
- delete this;
return false;
}
else {
int wr = write(iob.fd, pkt.data(), pkt.size());
if (wr == -1) {
if (errno == EPIPE) {
- delete this;
return false;
}
if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
// TODO log error
- delete this;
return false;
}
// EAGAIN etc: fall through to below
// We can't send out-of-memory response as we already wrote as much as we
// could above. Neither can we later send the response since we have currently
// sent an incomplete packet. All we can do is close the connection.
- delete this;
return false;
}
else {
if (r == -1) {
if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
// TODO log error
- delete this;
return true;
}
return false;
}
if (r == 0) {
- delete this;
return true;
}
// complete packet?
if (rbuf.get_length() >= chklen) {
try {
- return processPacket();
+ return !processPacket();
}
catch (std::bad_alloc &baexc) {
doOomClose();
char oomBuf[] = { DINIT_RP_OOM };
write(iob.fd, oomBuf, 1);
}
- delete this;
return true;
}
if (written == -1) {
if (errno == EPIPE) {
// read end closed
- delete this;
return true;
}
else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
}
else {
log(LogLevel::ERROR, "Error writing to control connection: ", strerror(errno));
- delete this;
return true;
}
return false;
iob.setWatchFlags(in_events);
}
else {
- delete this;
return true;
}
}
unsigned outpkt_index = 0;
// Queue a packet to be sent
- // Returns: false if the packet could not be queued and the connection has been
- // destroyed;
+ // Returns: false if the packet could not be queued and a suitable error packet
+ // could not be sent/queued (the connection should be closed);
// true (with bad_conn_close == false) if the packet was successfully
// queued;
// true (with bad_conn_close == true) if the packet was not successfully
- // queued.
+ // queued (but a suitable error packate has been queued).
// The in/out watch enabled state will also be set appropriately.
bool queuePacket(vector<char> &&v) noexcept;
bool queuePacket(const char *pkt, unsigned size) noexcept;
- // Process a packet. Can cause the ControlConn to be deleted iff there are no
- // outgoing packets queued (returns false).
+ // Process a packet.
+ // Returns: true (with bad_conn_close == false) if successful
+ // true (with bad_conn_close == true) if an error packet was queued
+ // false if an error occurred but no error packet could be queued
+ // (connection should be closed).
// Throws:
// std::bad_alloc - if an out-of-memory condition prevents processing
bool processPacket();
// Process an UNPINSERVICE packet. May throw std::bad_alloc.
bool processUnpinService();
- // Notify that data is ready to be read from the socket. Returns true if the connection was
- // deleted.
+ // Notify that data is ready to be read from the socket. Returns true if the connection should
+ // be closed.
bool dataReady() noexcept;
bool sendData() noexcept;
}
// Process service event broadcast.
+ // Note that this can potentially be called during packet processing (upon issuing
+ // service start/stop orders etc).
void serviceEvent(ServiceRecord * service, ServiceEvent event) noexcept final override
{
// For each service handle corresponding to the event, send an information packet.
ControlConn *conn = reinterpret_cast<ControlConn *>(cc_addr);
if (revents & in_events) {
if (conn->dataReady()) {
- // ControlConn was deleted
+ delete conn;
return Rearm::REMOVED;
}
}
if (revents & out_events) {
if (conn->sendData()) {
+ delete conn;
return Rearm::REMOVED;
}
}