Ejemplo n.º 1
0
bool MythSystemIOHandler::HandleRead(HANDLE h, QBuffer *buff)
{
    DWORD lenAvail;

    if ( !PeekNamedPipe( h, NULL, 0, NULL, &lenAvail, NULL) )
        return false;

    if ( lenAvail > 65536 )
        lenAvail = 65536;

    DWORD lenRead;

    if ( !ReadFile( h, &m_readbuf, lenAvail, &lenRead, NULL ) || lenRead == 0 )
    {
        m_pMap.remove(h);
        return false;
    }

    buff->buffer().append(m_readbuf, lenRead);

    // Get the corresponding MythSystem instance, and the stdout/stderr
    // type
    fdLock.lock();
    FDType_t *fdType = fdMap.value(h);
    fdLock.unlock();

    // Emit the data ready signal (1 = stdout, 2 = stderr)
    MythSystemWindows *ms = fdType->ms;
    emit ms->readDataReady(fdType->type);

    return true;
}
Ejemplo n.º 2
0
void MythSystemSignalManager::run(void)
{
    RunProlog();

    LOG(VB_GENERAL, LOG_INFO, "Starting process signal handler");
    while( run_system )
    {
        usleep(50000); // sleep 50ms
        while( run_system )
        {
            // handle cleanup and signalling for closed processes
            listLock.lock();
            if( msList.isEmpty() )
            {
                listLock.unlock();
                break;
            }
            MythSystemWindows *ms = msList.takeFirst();
            listLock.unlock();

            ms->m_parent->HandlePostRun();

            if (ms->m_stdpipe[0])
                writeThread->remove(ms->m_stdpipe[0]);
            CLOSE(ms->m_stdpipe[0]);

            if (ms->m_stdpipe[1])
                readThread->remove(ms->m_stdpipe[1]);
            CLOSE(ms->m_stdpipe[1]);

            if (ms->m_stdpipe[2])
                readThread->remove(ms->m_stdpipe[2]);
            CLOSE(ms->m_stdpipe[2]);

            if( ms->GetStatus() == GENERIC_EXIT_OK )
                emit ms->finished();
            else
                emit ms->error(ms->GetStatus());

            ms->disconnect();

            ms->Unlock();

            if( ms->m_parent->doAutoCleanup() )
                delete ms;
        }
    }

    RunEpilog();
}
Ejemplo n.º 3
0
void MythSystemManager::run(void)
{
    VERBOSE(VB_GENERAL|VB_SYSTEM, "Starting process manager");

    // gCoreContext is set to NULL during shutdown, and we need this thread to
    // exit during shutdown.
    while( gCoreContext )
    {
        // check for any running processes
        m_mapLock.lock();

        if( m_childCount == 0 )
        {
            m_mapLock.unlock();
            usleep( 100000 );
            continue;
        }

        DWORD result = WaitForMultipleObjects( m_childCount, m_children,
                                               FALSE, 100 );

        if ( result == WAIT_TIMEOUT || result == WAIT_FAILED )
        {
            m_mapLock.unlock();
            continue;
        }

        int index = result - WAIT_OBJECT_0;
        if ( index < 0 || index > m_childCount - 1 )
        {
            m_mapLock.unlock();
            continue;
        }
        HANDLE child = m_children[index];

        // pop exited process off managed list, add to cleanup list
        MythSystemWindows  *ms = m_pMap.take(child);
        ChildListRebuild();
        m_mapLock.unlock();

        listLock.lock();
        msList.append(ms);

        DWORD               status;
        GetExitCodeProcess( child, &status );

        ms->SetStatus(status);
        VERBOSE(VB_SYSTEM, 
                QString("Managed child (Handle: %1) has exited! "
                        "command=%2, status=%3, result=%4")
                .arg((long long)child) .arg(ms->GetLogCmd()) .arg(status) 
                .arg(ms->GetStatus()));

        // loop through running processes for any that require action
        MSMap_t::iterator   i;
        time_t              now = time(NULL);

        m_mapLock.lock();
        m_jumpLock.lock();
        for( i = m_pMap.begin(); i != m_pMap.end(); i++ )
        {
            child = i.key();
            ms    = i.value();

            // handle processes beyond marked timeout
            if( ms->m_timeout > 0 && ms->m_timeout < now )
            {
                // issuing KILL signal after TERM failed in a timely manner
                if( ms->GetStatus() == GENERIC_EXIT_TIMEOUT )
                {
                    VERBOSE(VB_SYSTEM, 
                        QString("Managed child (Handle: %1) timed out, "
                                "issuing KILL signal").arg((long long)child));
                    // Prevent constant attempts to kill an obstinate child
                    ms->m_timeout = 0;
                    ms->Signal(SIGKILL);
                }

                // issuing TERM signal
                else
                {
                    VERBOSE(VB_SYSTEM, 
                        QString("Managed child (Handle: %1) timed out"
                                ", issuing TERM signal").arg((long long)child));
                    ms->SetStatus( GENERIC_EXIT_TIMEOUT );
                    ms->m_timeout = now + 1;
                    ms->Term();
                }
            }

            if ( m_jumpAbort && ms->GetSetting("AbortOnJump") )
                ms->Term();
        }

        m_jumpAbort = false;
        m_jumpLock.unlock();

        m_mapLock.unlock();

        // hold off unlocking until all the way down here to 
        // give the buffer handling a chance to run before
        // being closed down by signal thread
        listLock.unlock();
    }

    // kick to allow them to close themselves cleanly
    readThread->wake();
    writeThread->wake();
}