Пример #1
0
void BlockingTCPAcceptor::destroy() {
    SOCKET sock;
    {
        Lock guard(_mutex);
        if(_destroyed) return;
        _destroyed = true;

        sock = _serverSocketChannel;
        _serverSocketChannel = INVALID_SOCKET;
    }

    if(sock!=INVALID_SOCKET) {
        char ipAddrStr[48];
        ipAddrToDottedIP(&_bindAddress.ia, ipAddrStr, sizeof(ipAddrStr));
        LOG(logLevelDebug, "Stopped accepting connections at %s.", ipAddrStr);

        switch(epicsSocketSystemCallInterruptMechanismQuery())
        {
        case esscimqi_socketBothShutdownRequired:
            shutdown(sock, SHUT_RDWR);
            epicsSocketDestroy(sock);
            _thread.exitWait();
            break;
        case esscimqi_socketSigAlarmRequired:
            LOG(logLevelError, "SigAlarm close not implemented for this target\n");
        case esscimqi_socketCloseRequired:
            epicsSocketDestroy(sock);
            _thread.exitWait();
            break;
        }
    }
}
        void BlockingUDPTransport::close(bool waitForThreadToComplete) {
            {
                Lock guard(_mutex);
                if(_closed.get()) return;
                _closed.set();
            }

            if (IS_LOGGABLE(logLevelDebug))
            {
                LOG(logLevelDebug,
                    "UDP socket %s closed.",
                    inetAddressToString(_bindAddress).c_str());
            }
            
            epicsSocketSystemCallInterruptMechanismQueryInfo info  =
                epicsSocketSystemCallInterruptMechanismQuery ();
            switch ( info )
            {
                case esscimqi_socketCloseRequired:
                    epicsSocketDestroy ( _channel );
                    break;
                case esscimqi_socketBothShutdownRequired:
                    {
                        /*int status =*/ ::shutdown ( _channel, SHUT_RDWR );
                        /*
                        if ( status ) {
                            char sockErrBuf[64];
                            epicsSocketConvertErrnoToString (
                                sockErrBuf, sizeof ( sockErrBuf ) );
                        LOG(logLevelDebug,
                            "UDP socket %s failed to shutdown: %s.",
                            inetAddressToString(_bindAddress).c_str(), sockErrBuf);
                        }
                        */
                        epicsSocketDestroy ( _channel );
                    }
                    break;
                case esscimqi_socketSigAlarmRequired:
                    // not supported anymore anyway
                default:
                    epicsSocketDestroy(_channel);
            }
            
            
            // wait for send thread to exit cleanly            
            if (waitForThreadToComplete)
            {
                if (!_shutdownEvent.wait(5.0))
                {
                    LOG(logLevelError,
                        "Receive thread for UDP socket %s has not exited.",
                        inetAddressToString(_bindAddress).c_str());
                }
            }
        }
Пример #3
0
/*
 *  cas_send_bs_msg()
 *
 *  (channel access server send message)
 */
void cas_send_bs_msg ( struct client *pclient, int lock_needed )
{
    int status;

    if ( CASDEBUG > 2 && pclient->send.stk ) {
        errlogPrintf ( "CAS: Sending a message of %d bytes\n", pclient->send.stk );
    }

    if ( pclient->disconnect ) {
        if ( CASDEBUG > 2 ) {
            errlogPrintf ( "CAS: msg Discard for sock %d addr %x\n",
                pclient->sock, (unsigned) pclient->addr.sin_addr.s_addr );
        }
        pclient->send.stk = 0u;
        return;
    }

    if ( lock_needed ) {
        SEND_LOCK ( pclient );
    }

    while ( pclient->send.stk && ! pclient->disconnect ) {
        status = send ( pclient->sock, pclient->send.buf, pclient->send.stk, 0 );
        if ( status >= 0 ) {
            unsigned transferSize = (unsigned) status;
            if ( transferSize >= pclient->send.stk ) {
                pclient->send.stk = 0;
                epicsTimeGetCurrent ( &pclient->time_at_last_send );
                break;
            }
            else {
                unsigned bytesLeft = pclient->send.stk - transferSize;
                memmove ( pclient->send.buf, &pclient->send.buf[transferSize], 
                    bytesLeft );
                pclient->send.stk = bytesLeft;
            }
        }
        else {
            int causeWasSocketHangup = 0;
            int anerrno = SOCKERRNO;
            char buf[64];

            if ( pclient->disconnect ) {
                pclient->send.stk = 0u;
                break;
            }

            if ( anerrno == SOCK_EINTR ) {
                continue;
            }

            if ( anerrno == SOCK_ENOBUFS ) {
                errlogPrintf (
                    "CAS: Out of network buffers, retrying send in 15 seconds\n" );
                epicsThreadSleep ( 15.0 );
                continue;
            }

            ipAddrToDottedIP ( &pclient->addr, buf, sizeof(buf) );

            if (    
                anerrno == SOCK_ECONNABORTED ||
                anerrno == SOCK_ECONNRESET ||
                anerrno == SOCK_EPIPE ||
                anerrno == SOCK_ETIMEDOUT ) {
                causeWasSocketHangup = 1;
            }
            else {
                char sockErrBuf[64];
                epicsSocketConvertErrnoToString ( 
                    sockErrBuf, sizeof ( sockErrBuf ) );
                errlogPrintf ( "CAS: TCP send to %s failed - %s\n",
                    buf, sockErrBuf);
            }
            pclient->disconnect = TRUE;
            pclient->send.stk = 0u;

            /*
             * wakeup the receive thread
             */
            if ( ! causeWasSocketHangup ) {
                enum epicsSocketSystemCallInterruptMechanismQueryInfo info  =
                    epicsSocketSystemCallInterruptMechanismQuery ();
                switch ( info ) {
                case esscimqi_socketCloseRequired:
                    if ( pclient->sock != INVALID_SOCKET ) {
                        epicsSocketDestroy ( pclient->sock );
                        pclient->sock = INVALID_SOCKET;
                    }
                    break;
                case esscimqi_socketBothShutdownRequired:
                    {
                        int status = shutdown ( pclient->sock, SHUT_RDWR );
                        if ( status ) {
                            char sockErrBuf[64];
                            epicsSocketConvertErrnoToString ( 
                                sockErrBuf, sizeof ( sockErrBuf ) );
                            errlogPrintf ("CAS: Socket shutdown error - %s\n", 
                                sockErrBuf );
                        }
                    }
                    break;
                case esscimqi_socketSigAlarmRequired:
                    epicsSignalRaiseSigAlarm ( pclient->tid );
                    break;
                default:
                    break;
                };
                break;
            }
        }
    }

    if ( lock_needed ) {
        SEND_UNLOCK(pclient);
    }

    DLOG ( 3, ( "------------------------------\n\n" ) );

    return;
}
Пример #4
0
/*
 * logClientDestroy
 */
static void logClientDestroy (logClientId id)
{
    enum epicsSocketSystemCallInterruptMechanismQueryInfo interruptInfo;
    logClient *pClient = (logClient *) id;
    epicsTimeStamp begin, current;
    double diff;

    /* command log client thread to shutdown - taking mutex here */
    /* forces cache flush on SMP machines */
    epicsMutexMustLock ( pClient->mutex );
    pClient->shutdown = 1u;
    epicsMutexUnlock ( pClient->mutex );

    /* unblock log client thread blocking in send() or connect() */
    interruptInfo =
        epicsSocketSystemCallInterruptMechanismQuery ();
    switch ( interruptInfo ) {
    case esscimqi_socketCloseRequired:
        logClientClose ( pClient );
        break;
    case esscimqi_socketBothShutdownRequired:
        shutdown ( pClient->sock, SHUT_WR );
        break;
    case esscimqi_socketSigAlarmRequired:
        epicsSignalRaiseSigAlarm ( pClient->restartThreadId );
        break;
    default:
        break;
    };

    /* wait for confirmation that the thread exited - taking */
    /* mutex here forces cache update on SMP machines */
    epicsTimeGetCurrent ( & begin );
    epicsMutexMustLock ( pClient->mutex );
    do {
        epicsMutexUnlock ( pClient->mutex );
        epicsEventWaitWithTimeout ( 
            pClient->stateChangeNotify, 
            LOG_SERVER_SHUTDOWN_TIMEOUT / 10.0 ); 
        epicsTimeGetCurrent ( & current );
        diff = epicsTimeDiffInSeconds ( & current, & begin );
        epicsMutexMustLock ( pClient->mutex );
    }
    while ( ! pClient->shutdownConfirm && diff < LOG_SERVER_SHUTDOWN_TIMEOUT );
    epicsMutexUnlock ( pClient->mutex );

    if ( ! pClient->shutdownConfirm ) {
        fprintf ( stderr, "log client shutdown: timed out stopping"
            " reconnect thread for \"%s\" after %.1f seconds - cleanup aborted\n",
            pClient->name, LOG_SERVER_SHUTDOWN_TIMEOUT );
        return;
    }

    logClientClose ( pClient );

    epicsMutexDestroy ( pClient->mutex );
   
    epicsEventDestroy ( pClient->stateChangeNotify );

    free ( pClient );
}