Ejemplo n.º 1
0
int vlc_cond_timedwait (vlc_cond_t *condvar, vlc_mutex_t *p_mutex,
                        mtime_t deadline)
{
    struct timespec ts = mtime_to_ts (deadline);
    vlc_thread_t th = thread;
    int (*cb)(pthread_cond_t *, pthread_mutex_t *, const struct timespec *);

    if (th != NULL)
    {
        vlc_testcancel ();
        if (vlc_mutex_trylock (&th->lock) == 0)
        {
            th->cond = &condvar->cond;
            vlc_mutex_unlock (&th->lock);
        }
        else
        {   /* The lock is already held by another thread.
             * => That other thread has just cancelled this one. */
            vlc_testcancel ();
            /* Cancellation did not occur even though this thread is cancelled.
             * => Cancellation is disabled. */
            th = NULL;
        }
    }

    switch (condvar->clock)
    {
         case CLOCK_REALTIME:
             cb = pthread_cond_timedwait;
             break;
         case CLOCK_MONOTONIC:
             cb = pthread_cond_timedwait_monotonic_np;
             break;
         default:
             assert (0);
    }

    int val = cb (&condvar->cond, p_mutex, &ts);
    if (val != ETIMEDOUT)
        VLC_THREAD_ASSERT ("timed-waiting on condition");

    if (th != NULL)
    {
        if (vlc_mutex_trylock (&th->lock) == 0)
        {
            thread->cond = NULL;
            vlc_mutex_unlock (&th->lock);
        }
        /* Else: This thread was cancelled and is cancellable.
                 vlc_testcancel() will take of it right there: */
        vlc_testcancel();
    }
    return val;
}
Ejemplo n.º 2
0
void mwait (mtime_t deadline)
{
    mtime_t delay;

    vlc_testcancel();
    while ((delay = (deadline - mdate())) > 0)
    {
        delay /= 1000;
        if (unlikely(delay > 0x7fffffff))
            delay = 0x7fffffff;
        vlc_Sleep (delay);
        vlc_testcancel();
    }
}
Ejemplo n.º 3
0
int vlc_mwait_i11e(mtime_t deadline)
{
    vlc_interrupt_t *ctx = vlc_threadvar_get(vlc_interrupt_var);
    if (ctx == NULL)
        return mwait(deadline), 0;

    vlc_cond_t wait;
    vlc_cond_init(&wait);

    int ret = vlc_interrupt_prepare(ctx, vlc_mwait_i11e_wake, &wait);
    if (ret)
    {
        vlc_cond_destroy(&wait);
        vlc_testcancel();
        return ret;
    }

    vlc_mutex_lock(&ctx->lock);
    vlc_cleanup_push(vlc_mwait_i11e_cleanup, ctx);
    while (!ctx->interrupted
        && vlc_cond_timedwait(&wait, &ctx->lock, deadline) == 0);
    vlc_cleanup_pop();
    vlc_mutex_unlock(&ctx->lock);

    ret = vlc_interrupt_finish(ctx);
    vlc_cond_destroy(&wait);
    return ret;
}
Ejemplo n.º 4
0
static void *SigThread (void *data)
{
    intf_thread_t *obj = data;
    sigset_t set;
    int signum;

    sigemptyset (&set);
    if (!ignored (SIGHUP)) /* <- needed to handle nohup properly */
        sigaddset (&set, SIGHUP);
    sigaddset (&set, SIGINT);
    sigaddset (&set, SIGQUIT);
    sigaddset (&set, SIGTERM);

    sigaddset (&set, SIGCHLD);

    do
    {
        while (sigwait (&set, &signum));

#ifdef __APPLE__
        /* In Mac OS X up to 10.5 sigwait (among others) is not a pthread
         * cancellation point */
        vlc_testcancel();
#endif

       /* Hack for Qt QProcess */
       if (signum == SIGCHLD)
       {
           struct sigaction act;

           sigaction (signum, NULL, &act);
           if ((act.sa_flags & SA_SIGINFO) || (act.sa_handler != SIG_DFL))
           {
               msg_Err (obj, "signal %d overriden (%p)", signum,
                        act.sa_handler);
#ifdef __GLIBC__
               Dl_info info;

               if (dladdr (act.sa_handler, &info))
                   msg_Err (obj, " %s(%s)[%p]",
                            info.dli_fname ? info.dli_fname : "?",
                            info.dli_sname ? info.dli_sname : "?",
                            info.dli_saddr);
#endif
               if (!(act.sa_flags & SA_SIGINFO) && (act.sa_handler != SIG_IGN))
                   act.sa_handler (signum);
           }
       }
    }
    while (signum == SIGCHLD);

    msg_Err (obj, "Caught %s signal, exiting...", strsignal (signum));
    libvlc_Quit (obj->p_libvlc);

    /* After 3 seconds, fallback to normal signal handling */
    msleep (3 * CLOCK_FREQ);
    pthread_sigmask (SIG_UNBLOCK, &set, NULL);
    for (;;)
        pause ();
}
Ejemplo n.º 5
0
int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
                        mtime_t deadline)
{
    DWORD result;

    do
    {
        vlc_testcancel ();

        mtime_t total = (deadline - mdate ())/1000;
        if( total < 0 )
            total = 0;

        DWORD delay = (total > 0x7fffffff) ? 0x7fffffff : total;
        LeaveCriticalSection (&p_mutex->mutex);
        result = WaitForSingleObjectEx (*p_condvar, delay, TRUE);
        EnterCriticalSection (&p_mutex->mutex);
    }
    while (result == WAIT_IO_COMPLETION);

    assert (result != WAIT_ABANDONED);
    assert (result != WAIT_FAILED);
    ResetEvent (*p_condvar);

    return (result == WAIT_OBJECT_0) ? 0 : ETIMEDOUT;
}
Ejemplo n.º 6
0
void vlc_sem_wait (vlc_sem_t *sem)
{
    ULONG rc;

    do
    {
        vlc_testcancel ();

        DosRequestMutexSem(sem->wait_mutex, SEM_INDEFINITE_WAIT);

        rc = vlc_WaitForSingleObject (sem->hev, SEM_INDEFINITE_WAIT );

        if (!rc)
        {
            DosRequestMutexSem(sem->count_mutex, SEM_INDEFINITE_WAIT);

            sem->count--;
            if (sem->count == 0)
            {
                ULONG ulPost;

                DosResetEventSem(sem->hev, &ulPost);
            }

            DosReleaseMutexSem(sem->count_mutex);
        }

        DosReleaseMutexSem(sem->wait_mutex);
    } while (rc == ERROR_INTERRUPT);
}
Ejemplo n.º 7
0
int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout)
{
    struct timespec tsbuf, *ts;
    sigset_t set;
    int canc, ret;

    if (timeout != -1)
    {
        div_t d = div (timeout, 1000);
        tsbuf.tv_sec = d.quot;
        tsbuf.tv_nsec = d.rem * 1000000;
        ts = &tsbuf;
    }
    else
        ts = NULL;

    pthread_sigmask (SIG_BLOCK, NULL, &set);
    sigdelset (&set, SIGRTMIN);

    canc = vlc_savecancel ();
    ret = ppoll (fds, nfds, ts, &set);
    vlc_restorecancel (canc);

    vlc_testcancel ();
    return ret;
}
Ejemplo n.º 8
0
static void Run( fingerprinter_thread_t *p_fingerprinter )
{
    fingerprinter_sys_t *p_sys = p_fingerprinter->p_sys;

    /* main loop */
    for (;;)
    {
        vlc_mutex_lock( &p_sys->processing.lock );
        mutex_cleanup_push( &p_sys->processing.lock );
        vlc_cond_timedwait( &p_sys->incoming_queue_filled, &p_sys->processing.lock, mdate() + 1000000 );
        vlc_cleanup_run();

        QueueIncomingRequests( p_sys );

        vlc_mutex_lock( &p_sys->processing.lock ); // L0
        mutex_cleanup_push( &p_sys->processing.lock );
        vlc_cleanup_push( cancelRun, p_sys ); // C1
//**
        for ( p_sys->i = 0 ; p_sys->i < vlc_array_count( p_sys->processing.queue ); p_sys->i++ )
        {
            fingerprint_request_t *p_data = vlc_array_item_at_index( p_sys->processing.queue, p_sys->i );
            acoustid_fingerprint_t acoustid_print;
            memset( &acoustid_print , 0, sizeof(acoustid_fingerprint_t) );
            vlc_cleanup_push( clearPrint, &acoustid_print ); // C2
            p_sys->psz_uri = input_item_GetURI( p_data->p_item );
            if ( p_sys->psz_uri )
            {
                /* overwrite with hint, as in this case, fingerprint's session will be truncated */
                if ( p_data->i_duration ) acoustid_print.i_duration = p_data->i_duration;

                DoFingerprint( VLC_OBJECT(p_fingerprinter), p_sys, &acoustid_print );

                DoAcoustIdWebRequest( VLC_OBJECT(p_fingerprinter), &acoustid_print );
                fill_metas_with_results( p_data, &acoustid_print );
                FREENULL( p_sys->psz_uri );
            }
            vlc_cleanup_run( ); // C2

            /* copy results */
            vlc_mutex_lock( &p_sys->results.lock );
            vlc_array_append( p_sys->results.queue, p_data );
            vlc_mutex_unlock( &p_sys->results.lock );

            vlc_testcancel();
        }

        if ( vlc_array_count( p_sys->processing.queue ) )
        {
            var_TriggerCallback( p_fingerprinter, "results-available" );
            vlc_array_clear( p_sys->processing.queue );
        }
        vlc_cleanup_pop( ); // C1
//**
        vlc_cleanup_run(); // L0
    }
}
Ejemplo n.º 9
0
void vlc_join (vlc_thread_t th, void **result)
{
    do
        vlc_testcancel ();
    while (vlc_WaitForSingleObject (th->id, INFINITE) == WAIT_IO_COMPLETION);

    if (result != NULL)
        *result = th->data;
    CloseHandle (th->id);
    free (th);
}
Ejemplo n.º 10
0
void vlc_sem_wait (vlc_sem_t *sem)
{
    DWORD result;

    do
    {
        vlc_testcancel ();
        result = vlc_WaitForSingleObject (*sem, INFINITE);
    }
    while (result == WAIT_IO_COMPLETION);
}
Ejemplo n.º 11
0
void vlc_cond_wait (vlc_cond_t *condvar, vlc_mutex_t *p_mutex)
{
    vlc_thread_t th = thread;

    if (th != NULL)
    {
        vlc_testcancel ();
        if (vlc_mutex_trylock (&th->lock) == 0)
        {
            th->cond = &condvar->cond;
            vlc_mutex_unlock (&th->lock);
        }
        else
        {   /* The lock is already held by another thread.
             * => That other thread has just cancelled this one. */
            vlc_testcancel ();
            /* Cancellation did not occur even though this thread is cancelled.
             * => Cancellation is disabled. */
            th = NULL;
        }
    }

    int val = pthread_cond_wait (&condvar->cond, p_mutex);
    VLC_THREAD_ASSERT ("waiting on condition");

    if (th != NULL)
    {
        if (vlc_mutex_trylock (&th->lock) == 0)
        {
            thread->cond = NULL;
            vlc_mutex_unlock (&th->lock);
        }
        /* Else: This thread was cancelled and is cancellable.
                 vlc_testcancel() will take of it right there: */
        vlc_testcancel();
    }
}
Ejemplo n.º 12
0
void vlc_join (vlc_thread_t handle, void **result)
{
    do
        vlc_testcancel ();
    while (WaitForSingleObjectEx (handle->handle, INFINITE, TRUE)
                                                        == WAIT_IO_COMPLETION);

    CloseHandle (handle->handle);
    if (result)
        *result = handle->data;
#ifdef UNDER_CE
    CloseHandle (handle->cancel_event);
#endif
    free (handle);
}
Ejemplo n.º 13
0
void vlc_sem_wait (vlc_sem_t *sem)
{
    HANDLE handle = vlc_sem_handle(sem);
    DWORD result;

    do
    {
        vlc_testcancel ();
        result = WaitForSingleObjectEx(handle, INFINITE, TRUE);

        /* Semaphore abandoned would be a bug. */
        assert(result != WAIT_ABANDONED_0);
    }
    while (result == WAIT_IO_COMPLETION || result == WAIT_FAILED);
}
Ejemplo n.º 14
0
void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex)
{
    DWORD result;

    do
    {
        vlc_testcancel ();
        LeaveCriticalSection (&p_mutex->mutex);
        result = WaitForSingleObjectEx (*p_condvar, INFINITE, TRUE);
        EnterCriticalSection (&p_mutex->mutex);
    }
    while (result == WAIT_IO_COMPLETION);

    assert (result != WAIT_ABANDONED); /* another thread failed to cleanup! */
    assert (result != WAIT_FAILED);
    ResetEvent (*p_condvar);
}
Ejemplo n.º 15
0
Archivo: thread.c Proyecto: Tilka/vlc
void vlc_join (vlc_thread_t th, void **result)
{
    ULONG rc;

    do
    {
        vlc_testcancel();
        rc = vlc_WaitForSingleObject( th->done_event, SEM_INDEFINITE_WAIT );
    } while( rc == ERROR_INTERRUPT );

    if (result != NULL)
        *result = th->data;

    DosCloseEventSem( th->cancel_event );
    DosCloseEventSem( th->done_event );

    free( th );
}
Ejemplo n.º 16
0
int vlc_sem_wait_i11e(vlc_sem_t *sem)
{
    vlc_interrupt_t *ctx = vlc_threadvar_get(vlc_interrupt_var);
    if (ctx == NULL)
        return vlc_sem_wait(sem), 0;

    int ret = vlc_interrupt_prepare(ctx, vlc_interrupt_sem, sem);
    if (ret)
    {
        vlc_testcancel();
        return ret;
    }

    vlc_cleanup_push(vlc_interrupt_cleanup, ctx);
    vlc_sem_wait(sem);
    vlc_cleanup_pop();

    return vlc_interrupt_finish(ctx);
}
Ejemplo n.º 17
0
Archivo: thread.c Proyecto: Tilka/vlc
int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
                        mtime_t deadline)
{
    ULONG   ulTimeout;
    ULONG   ulPost;
    ULONG   rc;

    if (!p_condvar->hev)
    {   /* FIXME FIXME FIXME */
        msleep (50000);
        return;
    }

    do
    {
        vlc_testcancel();

        mtime_t total;
        switch (p_condvar->clock)
        {
            case CLOCK_REALTIME: /* FIXME? sub-second precision */
                total = CLOCK_FREQ * time (NULL);
                break;
            default:
                assert (p_condvar->clock == CLOCK_MONOTONIC);
                total = mdate();
                break;
        }
        total = (deadline - total) / 1000;
        if( total < 0 )
            total = 0;

        ulTimeout = ( total > 0x7fffffff ) ? 0x7fffffff : total;

        vlc_mutex_unlock (p_mutex);
        rc = vlc_WaitForSingleObject( p_condvar->hev, ulTimeout );
        vlc_mutex_lock (p_mutex);
    } while( rc == ERROR_INTERRUPT );

    DosResetEventSem( p_condvar->hev, &ulPost );

    return rc ? ETIMEDOUT : 0;
}
Ejemplo n.º 18
0
int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
                        mtime_t deadline)
{
    DWORD result;

    if (!p_condvar->handle)
    {   /* FIXME FIXME FIXME */
        msleep (50000);
        return 0;
    }

    do
    {
        vlc_testcancel ();

        mtime_t total;
        switch (p_condvar->clock)
        {
            case CLOCK_REALTIME: /* FIXME? sub-second precision */
                total = CLOCK_FREQ * time (NULL);
                break;
            default:
                assert (p_condvar->clock == CLOCK_MONOTONIC);
                total = mdate();
                break;
        }
        total = (deadline - total) / 1000;
        if( total < 0 )
            total = 0;

        DWORD delay = (total > 0x7fffffff) ? 0x7fffffff : total;
        vlc_mutex_unlock (p_mutex);
        result = vlc_WaitForSingleObject (p_condvar->handle, delay);
        vlc_mutex_lock (p_mutex);
    }
    while (result == WAIT_IO_COMPLETION);

    ResetEvent (p_condvar->handle);

    return (result == WAIT_OBJECT_0) ? 0 : ETIMEDOUT;
}
Ejemplo n.º 19
0
void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex)
{
    DWORD result;

    if (!p_condvar->clock)
    {   /* FIXME FIXME FIXME */
        msleep (50000);
        return;
    }

    do
    {
        vlc_testcancel ();
        vlc_mutex_unlock (p_mutex);
        result = vlc_WaitForSingleObject (p_condvar->handle, INFINITE);
        vlc_mutex_lock (p_mutex);
    }
    while (result == WAIT_IO_COMPLETION);

    ResetEvent (p_condvar->handle);
}
Ejemplo n.º 20
0
Archivo: thread.c Proyecto: Tilka/vlc
void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex)
{
    ULONG ulPost;
    ULONG rc;

    if (!p_condvar->hev)
    {   /* FIXME FIXME FIXME */
        msleep (50000);
        return;
    }

    do
    {
        vlc_testcancel();

        vlc_mutex_unlock (p_mutex);
        rc = vlc_WaitForSingleObject( p_condvar->hev, SEM_INDEFINITE_WAIT );
        vlc_mutex_lock (p_mutex);
    } while( rc == ERROR_INTERRUPT );

    DosResetEventSem( p_condvar->hev, &ulPost );
}
Ejemplo n.º 21
0
int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout)
{
    size_t setsize = sizeof (fd_set) + nfds * sizeof (SOCKET);
    fd_set *rdset = malloc (setsize);
    fd_set *wrset = malloc (setsize);
    fd_set *exset = malloc (setsize);
    struct timeval tv = { 0, 0 };
    int val;

    if (unlikely(rdset == NULL || wrset == NULL || exset == NULL))
    {
        free (rdset);
        free (wrset);
        free (exset);
        errno = ENOMEM;
        return -1;
    }

/* Winsock FD_SET uses FD_SETSIZE in its expansion */
#undef FD_SETSIZE
#define FD_SETSIZE (nfds)

resume:
    val = -1;
    vlc_testcancel ();

    FD_ZERO (rdset);
    FD_ZERO (wrset);
    FD_ZERO (exset);
    for (unsigned i = 0; i < nfds; i++)
    {
        int fd = fds[i].fd;
        if (val < fd)
            val = fd;

        /* With POSIX, FD_SET & FD_ISSET are not defined if fd is negative or
         * bigger or equal than FD_SETSIZE. That is one of the reasons why VLC
         * uses poll() rather than select(). Most POSIX systems implement
         * fd_set has a bit field with no sanity checks. This is especially bad
         * on systems (such as BSD) that have no process open files limit by
         * default, such that it is quite feasible to get fd >= FD_SETSIZE.
         * The next instructions will result in a buffer overflow if run on
         * a POSIX system, and the later FD_ISSET would perform an undefined
         * memory read.
         *
         * With Winsock, fd_set is a table of integers. This is awfully slow.
         * However, FD_SET and FD_ISSET silently and safely discard excess
         * entries. Here, overflow cannot happen anyway: fd_set of adequate
         * size are allocated.
         * Note that Vista has a much nicer WSAPoll(), but Mingw does not
         * support it yet.
         */
        if (fds[i].events & POLLIN)
            FD_SET ((SOCKET)fd, rdset);
        if (fds[i].events & POLLOUT)
            FD_SET ((SOCKET)fd, wrset);
        if (fds[i].events & POLLPRI)
            FD_SET ((SOCKET)fd, exset);
    }

#ifndef HAVE_ALERTABLE_SELECT
# warning FIXME! Fix cancellation and remove this crap.
    if ((timeout < 0) || (timeout > 50))
    {
        tv.tv_sec = 0;
        tv.tv_usec = 50000;
    }
    else
#endif
    if (timeout >= 0)
    {
        div_t d = div (timeout, 1000);
        tv.tv_sec = d.quot;
        tv.tv_usec = d.rem * 1000;
    }

    val = select (val + 1, rdset, wrset, exset,
                  /*(timeout >= 0) ?*/ &tv /*: NULL*/);

#ifndef HAVE_ALERTABLE_SELECT
    if (val == 0)
    {
        if (timeout > 0)
            timeout -= (timeout > 50) ? 50 : timeout;
        if (timeout != 0)
            goto resume;
    }
#endif

    if (val == -1)
        return -1;

    for (unsigned i = 0; i < nfds; i++)
    {
        int fd = fds[i].fd;
        fds[i].revents = (FD_ISSET (fd, rdset) ? POLLIN : 0)
                       | (FD_ISSET (fd, wrset) ? POLLOUT : 0)
                       | (FD_ISSET (fd, exset) ? POLLPRI : 0);
    }
    free (exset);
    free (wrset);
    free (rdset);
    return val;
}
Ejemplo n.º 22
0
/*****************************************************************************
 * Run :
 *****************************************************************************/
static void *Run( void *opaque )
{
    fingerprinter_thread_t *p_fingerprinter = opaque;
    fingerprinter_sys_t *p_sys = p_fingerprinter->p_sys;

    vlc_mutex_lock( &p_sys->processing.lock );
    mutex_cleanup_push( &p_sys->processing.lock );

    /* main loop */
    for (;;)
    {
        msleep( CLOCK_FREQ );

        QueueIncomingRequests( p_sys );

        vlc_testcancel();

        for ( size_t i = 0 ; i < vlc_array_count( &p_sys->processing.queue ); i++ )
        {
            int canc = vlc_savecancel();
            fingerprint_request_t *p_data = vlc_array_item_at_index( &p_sys->processing.queue, i );

            char *psz_uri = input_item_GetURI( p_data->p_item );
            if ( psz_uri != NULL )
            {
                 acoustid_fingerprint_t acoustid_print;

                 memset( &acoustid_print , 0, sizeof (acoustid_print) );
                /* overwrite with hint, as in this case, fingerprint's session will be truncated */
                if ( p_data->i_duration )
                     acoustid_print.i_duration = p_data->i_duration;

                DoFingerprint( p_fingerprinter, &acoustid_print, psz_uri );
                free( psz_uri );

                DoAcoustIdWebRequest( VLC_OBJECT(p_fingerprinter), &acoustid_print );
                fill_metas_with_results( p_data, &acoustid_print );

                for( unsigned j = 0; j < acoustid_print.results.count; j++ )
                     free_acoustid_result_t( &acoustid_print.results.p_results[j] );
                if( acoustid_print.results.count )
                    free( acoustid_print.results.p_results );
                free( acoustid_print.psz_fingerprint );
            }
            vlc_restorecancel(canc);

            /* copy results */
            vlc_mutex_lock( &p_sys->results.lock );
            vlc_array_append( &p_sys->results.queue, p_data );
            vlc_mutex_unlock( &p_sys->results.lock );

            vlc_testcancel();
        }

        if ( vlc_array_count( &p_sys->processing.queue ) )
        {
            var_TriggerCallback( p_fingerprinter, "results-available" );
            vlc_array_clear( &p_sys->processing.queue );
        }
    }

    vlc_cleanup_pop();
    vlc_assert_unreachable();
}
Ejemplo n.º 23
0
static void Run(intf_thread_t *p_intf) {
    intf_sys_t *p_sys = p_intf->p_sys;
    input_thread_t *p_input = NULL;
    playlist_t *p_playlist = pl_Get(p_intf);
    int *pi_fd, i_listen = 0, i_err;

    p_intf->p_sys->p_playlist = p_playlist;

    for (pi_fd = p_sys->pi_socket; *pi_fd != -1; pi_fd++)
        i_listen++;
    for (; vlc_object_alive(p_intf);) {
        vlc_value_t val;
        struct pollfd fd[i_listen + 2];

        vlc_testcancel();

        if (p_input == NULL) {
            p_input = playlist_CurrentInput(p_playlist);
            if (p_input) {
                var_AddCallback(p_input, "intf-event", InputEvent, p_intf);
            }
        }
        else {
            if (p_input->b_dead || !vlc_object_alive(p_input)) {
                var_DelCallback(p_input, "intf-event", InputEvent, p_intf);
                vlc_object_release(p_input);
                p_input = NULL;
            }
        }
        memset(&fd, 0, sizeof(fd[0]) * (i_listen + 1));
        if (p_sys->i_socket == -1) {
            for (int i = 0; i < i_listen; i++) {
                fd[i].fd = p_sys->pi_socket[i];
                fd[i].events = POLLIN;
                fd[i].revents = 0;
            }
        }
        else {
            fd[0].fd = p_sys->i_wakeup[0];
            fd[0].events = POLLIN;
            fd[0].revents = 0;
            fd[1].fd = p_sys->i_socket;
            fd[1].events = POLLIN | (p_sys->i_write_length > 0 ? POLLOUT : 0);
            fd[1].revents = 0;
        }
        i_err = poll(fd, (p_sys->i_socket != -1) ? 2 : i_listen, -1);
        if (i_err < 0) {
            msg_Dbg(p_intf, "poll() failed");
            vlc_object_kill(p_intf);
            break;
        }
        if (i_err == 0)
            continue;
        if (p_sys->i_socket == -1) {
            for (int i = 0; i < i_listen; i++) {
                if (fd[i].revents & POLLIN) {
                    int client = net_AcceptSingle(VLC_OBJECT(p_intf), fd[i].fd);
                    if (client == -1)
                        continue;
                    p_sys->i_socket = client;
                    break;
                }
            }
        }
        else {
            if (fd[0].revents & POLLIN) {
                char ch;

                read(fd[0].fd, &ch, 1);
            }
            if (fd[1].revents & (POLLERR|POLLHUP|POLLNVAL)) {
                net_Close(fd[0].fd);
                p_sys->i_socket = -1;
                msg_Dbg(VLC_OBJECT(p_intf), "connection error");
                continue;
            }
            ssize_t i_len, i_test;
            if (fd[1].revents & POLLIN) {
                //msg_Dbg(VLC_OBJECT(p_intf), "poll in");
                bool b_line = false;
                while ((i_len = recv(fd[1].fd, p_sys->p_read_buffer + p_sys->i_read_offset, 1, 0)) > 0) {
                    char ch;

                    ch = p_sys->p_read_buffer[p_sys->i_read_offset];
                    switch (ch) {
                    case '\r':
                    case '\n':
                        p_sys->p_read_buffer[p_sys->i_read_offset] = '\0';
                        b_line = true;
                        break;
                    case '\0':
                        b_line = true;
                        break;
                    default:
                        break;
                    }
                    p_sys->i_read_offset++;
                    if (p_sys->i_read_offset == sizeof(p_sys->p_read_buffer) && !b_line) {
                        net_Close(p_sys->i_socket);
                        p_sys->i_socket = -1;
                        msg_Dbg(VLC_OBJECT(p_intf), "input is too long, close connection");
                        break;
                    }
                }
                if (b_line && strlen(p_sys->p_read_buffer)) {
                    p_sys->i_read_offset = 0;
                    //msg_Dbg(VLC_OBJECT(p_intf), "%s\n", p_sys->p_read_buffer);
                    ProcessCommand(p_intf, p_sys->p_read_buffer);
                }
                if(i_len == 0) {
                    net_Close(p_sys->i_socket);
                    p_sys->i_socket = -1;
                    msg_Dbg(VLC_OBJECT(p_intf), "connection is closed by client");
                }
            }
            if (fd[1].revents & POLLOUT) {
                vlc_mutex_lock(&p_sys->o_write_lock);
                if (p_sys->i_write_length) {
                    int i_first, i_second;

                    i_first = sizeof(p_sys->p_write_buffer) - p_sys->i_write_offset;
                    i_second = (p_sys->i_write_offset + p_sys->i_write_length) % sizeof(p_sys->p_write_buffer);
                    i_test = 0;
                    if (i_first >= p_sys->i_write_length)
                        i_len = send(fd[1].fd, p_sys->p_write_buffer + p_sys->i_write_offset, p_sys->i_write_length, 0);
                    else {
                        i_len = send(fd[1].fd, p_sys->p_write_buffer + p_sys->i_write_offset, i_first, 0);
                        if (i_len == i_first)
                            i_test = send(fd[1].fd, p_sys->p_write_buffer, i_second, 0);
                        if (i_test > 0)
                            i_len += i_test;
                    }
                    if (i_len > 0) {
                        p_sys->i_write_offset += i_len;
                        p_sys->i_write_offset %= sizeof(p_sys->p_write_buffer);
                        p_sys->i_write_length -= i_len;
                        if (p_sys->i_write_length == 0)
                            p_sys->i_write_offset = 0;
                    }
                }
                vlc_mutex_unlock(&p_sys->o_write_lock);
            }
        }
    }
}