Beispiel #1
0
/* Remove FILEs, honoring options specified via X.
   Return RM_OK if successful.  */
enum RM_status
rm (char *const *file, struct rm_options const *x)
{
  enum RM_status rm_status = RM_OK;

  if (*file)
    {
      int bit_flags = (FTS_CWDFD
                       | FTS_NOSTAT
                       | FTS_PHYSICAL);

      if (x->one_file_system)
        bit_flags |= FTS_XDEV;

      FTS *fts = xfts_open (file, bit_flags, NULL);

      while (1)
        {
          FTSENT *ent;

          ent = fts_read (fts);
          if (ent == NULL)
            {
              if (errno != 0)
                {
                  error (0, errno, _("fts_read failed"));
                  rm_status = RM_ERROR;
                }
              break;
            }

          enum RM_status s = rm_fts (fts, ent, x);

          assert (VALID_STATUS (s));
          UPDATE_STATUS (rm_status, s);
        }

      if (fts_close (fts) != 0)
        {
          error (0, errno, _("fts_close failed"));
          rm_status = RM_ERROR;
        }
    }

  return rm_status;
}
Beispiel #2
0
void AmeCtrlJobList::OnChar(wxKeyEvent& event){
	//POP(SP1("%d", event.GetKeyCode()));
	if(event.GetKeyCode()<128){
		long item = NEXT(-1);
		if(item>-1){
			AmeJob *j = GET(item);
			AdbFile *f = j->getAdbFile();
			if(f){
				switch(event.GetKeyCode()){
					case 'A': MYEXEC(f->urlAnime()); break;
					case 'M': MYEXEC(f->urlMylist()); break;
					case 'N': MYEXEC(f->urlMylistX()); break;
					case 'E': MYEXEC(f->urlEpisode()); break;
					case 'G': MYEXEC(f->urlGroup()); break;
					case 'F': MYEXEC(f->urlFile()); break;
					case 'K': MYEXEC(f->urlExport()); break;
					case 'C': AVDUMP(j->getAbsolutePath()); MYEXEC(f->urlFile()); break;
				}
			}
			switch(event.GetKeyCode()){
				case 'W': MYEXEC(j->getAbsolutePath()); break;
				case 'X': MYEXPL(j->getFolderPath()); break;
				case 'P': {UPDATE_STATUS(jH_PAUSED);} break;
				case 'S': AmeJobMan::updateStatus(j, jIDENTIFIED); break;
				case 'I':
					j->deleteAdbFile();
					AmeJobMan::updateStatus(j, jHASHED); break;
				case ' ':
				case 13: showInfo(this); break;
				//case 39: if(m_tt!=null) m_tt.expandRow(); break;
				//case 37: if(m_tt!=null) m_tt.collapseRow(); break;
				//default: POP(SP1("%d", event.GetKeyCode()));
			}
		}
	}else event.Skip();
}
Beispiel #3
0
/*
 * Initialize the transaction descriptor before start or restart.
 */
static inline void stm_prepare(stm_tx_t *tx)
{
 start:
  /* Start timestamp */
  tx->start = tx->end = GET_CLOCK; /* OPT: Could be delayed until first read/write */

  /* Allow extensions */
  tx->can_extend = 1;
  if (tx->start >= VERSION_MAX) {
    /* Block all transactions and reset clock */
    stm_quiesce_barrier(tx, rollover_clock, NULL);
    goto start;
  }
  /* Read/write set */
  tx->w_set.has_writes = 0;
  tx->w_set.nb_entries = 0;
  tx->r_set.nb_entries = 0;


  /* Set status */
  UPDATE_STATUS(tx->status, TX_ACTIVE);

  stm_check_quiesce(tx);
}
Beispiel #4
0
//
// LoadResources
//
void Game::LoadResources()
{
	int i;
	static bool Loaded = false;
	char filename[MAX_STR_LENGTH], completeFilename[MAX_STR_LENGTH];

	if(!Loaded)
	{

		UPDATE_STATUS("Loading resources...");

		for(i=0; i<MAX_SPRITES; i++)
			spriteImgs[i] = NULL;

		for(i=0; i<MAX_TEXTURES; i++)
		{
			textures[i][0] = NULL;
			textures[i][1] = NULL;
		}

		UPDATE_STATUS("Loading textures...");


		for(i=0; i<MAX_TEXTURES; i++)
		{
			sprintf(filename, "textures/map1/tex%d.bmp",i+1);
			sprintf(completeFilename, "%s%s", DATA_PREFIX, filename);
			if(framework->FileExists(completeFilename))
			{
				textures[i][0] = framework->LoadImage(filename, false);
				sprintf(filename, "textures/map1/tex%dDark.bmp", i+1);
				textures[i][1] = framework->LoadImage(filename, false);
			}
			else
				break;
		}

		numTextures = i;

		UPDATE_STATUS("Loading sprites...");

		for(i=0; i<MAX_SPRITES; i++)
		{
			sprintf(filename, "sprites/map1/sprite%d.bmp", i+1);
			sprintf(completeFilename, "%s%s", DATA_PREFIX, filename);
			if(framework->FileExists(completeFilename))
				spriteImgs[i] = framework->LoadImage(filename, true);
			else
				break;
		}
	}
	UPDATE_STATUS("Loading ui images...");

	if(lowQuality)
	{
		hudBgImg = framework->LoadImage("images\\lowQuality\\hudBg.bmp", false);
		crosshairImg = framework->LoadImage("images\\lowQuality\\crosshair.bmp", true);
		headImg = framework->LoadImage("images\\lowQuality\\head.bmp", true);
		headRedImg = framework->LoadImage("images\\lowQuality\\headRed.bmp", true);
		gunHudImg = framework->LoadImage("images\\lowQuality\\gunHud.bmp", true);
		gunImg = framework->LoadImage("images\\lowQuality\\gun.bmp", true);
		fireImg = framework->LoadImage("images\\lowQuality\\fire.bmp", true);
		keyImg = framework->LoadImage("images\\lowQuality\\key.bmp", true);
	}

	else
	{
		hudBgImg = framework->LoadImage("images/hudBg.bmp", false);
		crosshairImg = framework->LoadImage("images/crosshair.bmp", true);
		headImg = framework->LoadImage("images/head.bmp", true);
		headRedImg = framework->LoadImage("images/headRed.bmp", true);
		gunHudImg = framework->LoadImage("images/gunHud.bmp", true);
		gunImg = framework->LoadImage("images/gun.bmp", true);
		fireImg = framework->LoadImage("images/fire.bmp", true);
		keyImg = framework->LoadImage("images/key.bmp", true);
		MGgunImg = framework->LoadImage("images/mg.bmp", true);
		MGfireImg = framework->LoadImage("images/mg_fire.bmp", true);
		MGgunHudImg = framework->LoadImage("images/mg_Hud.bmp", true);

		SDL_SetAlpha(hudBgImg, SDL_SRCALPHA, SDL_ALPHA_OPAQUE / 2);
		SDL_SetAlpha(headRedImg, SDL_SRCALPHA, SDL_ALPHA_OPAQUE / 2);
	}

	crosshairRect.x = (framework->GetScrW() - crosshairImg->w) / 2;
	crosshairRect.y = (framework->GetScrH() - crosshairImg->h) / 2;
	crosshairRect.w = crosshairImg->w;
	crosshairRect.h = crosshairImg->h;

	UPDATE_STATUS("Loading Music resources...");



	if(!framework->GetNoSound())
	{
		if(!Loaded)
		{
			music1 = framework->LoadMusic("music/music1.ogg");
			Loaded = true;
		}
		UPDATE_STATUS("Loading Sounds resources...");

		startSnd = framework->LoadSound("sounds/startround.ogg");
		shootSnd = framework->LoadSound("sounds/shot.ogg");
		killSnd = framework->LoadSound("sounds/scream.ogg");
		pickAmmoSnd = framework->LoadSound("sounds/pickammo.ogg");
		PlayerHurt = framework->LoadSound("sounds/PlayerHurt.ogg");
		EnemyHurt = framework->LoadSound("sounds/EnemyHurt.ogg");
		PlayerDead = framework->LoadSound("sounds/PlayerDead.ogg");
		pickKey = framework->LoadSound("sounds/pickKey.ogg");
		pickHealth = framework->LoadSound("sounds/pickHealth.ogg");
		LVLClear = framework->LoadSound("sounds/LVLClear.ogg");
		MGshootSnd = framework->LoadSound("sounds/MGshoot.ogg");
		HeartBeat = framework->LoadSound("sounds/HeartBeat.ogg");

		UPDATE_STATUS("Loading Extra Sounds resources...");
		framework->GlobalSounds();
	}

}
Beispiel #5
0
sigjmp_buf *
hytm_start(TXPARAMS stm_tx_attr_t attr)
{
    TX_GET;
    unsigned long err;

    tx->retries = 0;
    /* Set status */
    UPDATE_STATUS(tx->status, TX_ACTIVE);
    stm_check_quiesce(tx);
    /* copy attributes if need to switch to software mode */
    tx->attr = attr;
    tx->start = rdtsc();

hytm_restart:
    /* All registers are lost when ASF aborts, thus we discard registers */
    asm volatile (ASF_SPECULATE
                  :"=a" (err)
                  :
                  :"memory","rbp","rbx","rcx","rdx","rsi","rdi",
                  "r8", "r9","r10","r11","r12","r13","r14","r15" );

    tx = tls_get_tx();
    if (unlikely(asf_status_code(err) != 0)) {
        /* Set status to ABORTED */
        SET_STATUS(tx->status, TX_ABORTED);
        tx->retries++;
        /* Error management */
        if (asf_status_code(err) == ASF_STATUS_CONTENTION) {
            if (tx->retries > ASF_ABORT_THRESHOLD) {
                /* There is too many conflicts, software will not help, start irrevocability. */
                stm_set_irrevocable(TXARGS 1);  /* Set irrevocable serial */
#if defined(TM_DTMC) || defined(TM_GCC)
                stm_set_irrevocable(TXARGS -1); /* Acquire irrevocability */
                UPDATE_STATUS(tx->status, TX_IRREVOCABLE);
                LONGJMP(tx->env, 0x02); /* ABI 0x02 = runUninstrumented */
#else /* ! defined(TM_DTMC) && ! defined(TM_GCC) */
                /* Non-tm compiler doesn't have path without instrumentation. */
                tx->software = 1;
#endif /* ! defined(TM_DTMC) && ! defined(TM_GCC) */
            }
        } else if (asf_status_code(err) == ASF_STATUS_ABORT) {
            if (asf_abort_code(err) == ASF_FORCE_SOFTWARE) {
                tx->software = 1;
#ifdef IRREVOCABLE_ENABLED
            } else if(asf_abort_code(err) == ASF_RETRY_IRREVOCABLE) {
# if defined(TM_DTMC) || defined(TM_GCC)
                if (tx->irrevocable != 0) {
                    stm_set_irrevocable(TXARGS -1);
                    UPDATE_STATUS(tx->status, TX_IRREVOCABLE);
                    LONGJMP(tx->env, 0x02); /* ABI 0x02 = runUninstrumented */
                }
# else /* ! defined(TM_DTMC) || defined(TM_GCC) */
                /* Non-tm compiler doesn't have path without instrumentation. */
                tx->software = 1;
# endif /* ! defined(TM_DTMC) || defined(TM_GCC) */
#endif /* IRREVOCABLE_ENABLED */
            } else {
                if (tx->retries > ASF_ABORT_THRESHOLD) {
                    tx->software = 1;
                }
            }
        } else {
            /* Other cases are critical and needs software mode */
            tx->software = 1;
        }
        if (tx->software) {
            /* Start a software transaction (it cannot use attr since the register/stack can be corrupted) */
            stm_start(TXARGS tx->attr);
            /* Restoring the context */
#if defined(TM_DTMC)
            LONGJMP(tx->env, 0x01); /* ABI 0x01 = runInstrumented, DTMC explicitly needs 1 */
#else /* ! defined(TM_DTMC) */
            LONGJMP(tx->env, 0x09); /* ABI 0x09 = runInstrumented + restoreLiveVariable */
#endif /* ! defined(TM_DTMC) */
        } else {
            uint64_t cur = (uint64_t)rdtsc();
            uint64_t wait = cur + (random() % (cur - tx->start)); /* XXX random but maybe not reliable */
            /* Waiting... */
            while (rdtsc() < wait);
            UPDATE_STATUS(tx->status, TX_ACTIVE);
            /* Check quiesce before to restart */
            stm_check_quiesce(tx);
            goto hytm_restart;
        }
    }

    /* Reset write set */
    tx->w_set.nb_entries = 0;

    if (tx->retries > 0) {
        /* Restoring registers for retry */
#if defined(TM_DTMC)
        LONGJMP(tx->env, 0x01); /* ABI 0x01 = runInstrumented, DTMC explicitly needs 1 */
#else /* ! defined(TM_DTMC) */
        LONGJMP(tx->env, 0x09); /* ABI 0x09 = runInstrumented + restoreLiveVariable */
#endif /* ! defined(TM_DTMC) */
    }

    return &tx->env;
}
Beispiel #6
0
void AmeCtrlJobList::DoApplyRules(wxCommandEvent& WXUNUSED(event)){
	UPDATE_STATUS(jIDENTIFIED);
}
Beispiel #7
0
void AmeCtrlJobList::DoPause(wxCommandEvent& WXUNUSED(event)){
	UPDATE_STATUS(jH_PAUSED);
}
Beispiel #8
0
	UPDATE_STATUS(jIDENTIFIED);
}
void AmeCtrlJobList::DoWatchNow(wxCommandEvent& WXUNUSED(event)){
	AmeJob *j = GetSelectedJob();
	if(j&&!j->check(jH_MISSING)){
		MYEXEC(j->getAbsolutePath());
	}
}
void AmeCtrlJobList::DoExploreFolder(wxCommandEvent& WXUNUSED(event)){
	AmeJob *j = GetSelectedJob();
	if(j&&!j->check(jH_MISSING)){
		MYEXPL(j->getFolderPath());
	}
}
void AmeCtrlJobList::DoReHash(wxCommandEvent& WXUNUSED(event)){
	UPDATE_STATUS(jHASHWAIT)
}
void AmeCtrlJobList::DoReId(wxCommandEvent& WXUNUSED(event)){
	UPDATE_STATUS(jHASHED)
}
void AmeCtrlJobList::DoReAdd(wxCommandEvent& WXUNUSED(event)){
	UPDATE_STATUS(jADDWAIT)
}
void AmeCtrlJobList::DoRemove(wxCommandEvent& WXUNUSED(event)){
	UPDATE_STATUS(jREMWAIT)
}
void AmeCtrlJobList::DoSetFinished(wxCommandEvent& WXUNUSED(event)){
	UPDATE_STATUS(jFINISHED)
}
void AmeCtrlJobList::DoRestoreName(wxCommandEvent& WXUNUSED(event)){
	REFRESH_BLOCK(AmeJobMan::restoreName(j));
Beispiel #9
0
static void *
__sandbox_tracer(sandbox_t * psbox)
{
    FUNC_BEGIN("sandbox_tracer(%p)", psbox);

    assert(psbox);

    #define UPDATE_RESULT(psbox,res) \
    {{{ \
        if (((psbox)->result) != (result_t)(res)) \
        { \
            ((psbox)->result) = (result_t)(res); \
        } \
        DBG("result: %s", s_result_name((result_t)(res))); \
    }}} /* UPDATE_RESULT */

    #define UPDATE_STATUS(psbox,sta) \
    {{{ \
        P(&((psbox)->mutex)); \
        if (((psbox)->status) != (status_t)(sta)) \
        { \
            ((psbox)->status) = (status_t)(sta); \
            pthread_cond_broadcast(&((psbox)->update)); \
        } \
        V(&((psbox)->mutex)); \
        DBG("status: %s", s_status_name((status_t)(sta))); \
    }}} /* UPDATE_STATUS */

    #define SIGMLE SIGUSR1

    #define TIMEVAL_INPLACE_SUBTRACT(x,y) \
    {{{ \
        if ((x).tv_usec < (y).tv_usec) \
        { \
            int nsec = ((y).tv_usec - (x).tv_usec) / 1000000 + 1; \
            (x).tv_sec -= nsec; \
            (x).tv_usec += 1000000 * nsec; \
        } \
        if ((x).tv_usec - (y).tv_usec >= 1000000) \
        { \
            int nsec = ((y).tv_usec - (x).tv_usec) / 1000000; \
            (x).tv_usec -= 1000000 * nsec; \
            (x).tv_sec += nsec; \
        } \
        (x).tv_sec -= (y).tv_sec; \
        (x).tv_usec -= (y).tv_usec; \
    }}} /* TIMEVAL_INPLACE_SUBTRACT */

    #define CLEAR_EVENT(pctrl) \
    {{{ \
        P(&((pctrl)->mutex)); \
        ((pctrl)->idle) = true; \
        pthread_cond_broadcast(&((pctrl)->sched)); \
        V(&((pctrl)->mutex)); \
    }}} /* CLEAR_EVENT */

    #define POST_EVENT(pctrl,type,x...) \
    {{{ \
        P(&((pctrl)->mutex)); \
        ((pctrl)->event) = (event_t){(S_EVENT ## type), {{x}}}; \
        ((pctrl)->idle) = false; \
        pthread_cond_broadcast(&((pctrl)->sched)); \
        V(&((pctrl)->mutex)); \
    }}} /* POST_EVENT */

#ifdef WITH_CUSTOM_MONITOR
    #define SINK_EVENT(pctrl) \
    {{{ \
        P(&((pctrl)->mutex)); \
        while (!IS_IDLE(pctrl)) \
        { \
            pthread_cond_wait(&((pctrl)->sched), &((pctrl)->mutex)); \
        } \
        V(&((pctrl)->mutex)); \
    }}} /* SINK_EVENT */
#endif /* WITH_CUSTOM_MONITOR */

#ifdef WITH_NATIVE_MONITOR
    #define SINK_EVENT(pctrl) \
    {{{ \
        P(&((pctrl)->mutex)); \
        if (IS_IDLE(pctrl)) \
        { \
            DBG("no event detected"); \
            V(&((pctrl)->mutex)); \
            goto cont; \
        } \
        V(&((pctrl)->mutex)); \
        \
        DBG("detected event: %s {%lu %lu %lu %lu %lu %lu %lu}", \
            s_event_type_name((pctrl)->event.type), \
            (pctrl)->event.data.__bitmap__.A, \
            (pctrl)->event.data.__bitmap__.B, \
            (pctrl)->event.data.__bitmap__.C, \
            (pctrl)->event.data.__bitmap__.D, \
            (pctrl)->event.data.__bitmap__.E, \
            (pctrl)->event.data.__bitmap__.F, \
            (pctrl)->event.data.__bitmap__.G); \
        \
        ((policy_entry_t)(pctrl)->policy.entry)(&(pctrl)->policy, \
                                                &(pctrl)->event, \
                                                &(pctrl)->action); \
        \
        DBG("decided action: %s {%lu %lu}", \
            s_action_type_name((pctrl)->action.type), \
            (pctrl)->action.data.__bitmap__.A, \
            (pctrl)->action.data.__bitmap__.B); \
        \
        P(&((pctrl)->mutex)); \
        ((pctrl)->idle) = true; \
        pthread_cond_broadcast(&((pctrl)->sched)); \
        V(&((pctrl)->mutex)); \
    }}} /* SINK_EVENT */
#endif /* WITH_NATIVE_MONITOR */

    DBG("entering: the tracing thread");

    /* The controller should contain pid of the prisoner process */
    pid_t pid = psbox->ctrl.pid;

    /* Check if the prisoner process was correctly forked */
    if (pid < 0)
    {
        WARNING("error forking the prisoner process");
        UPDATE_RESULT(psbox, S_RESULT_IE);
        UPDATE_STATUS(psbox, S_STATUS_FIN);
        FUNC_RET((void *)&psbox->result, "sandbox_tracer()");
    }

    /* Have signals kill the prisoner but not self (if possible).  */
    sighandler_t terminate_signal;
    sighandler_t interrupt_signal;
    sighandler_t quit_signal;

    terminate_signal = signal(SIGTERM, SIG_IGN);
    interrupt_signal = signal(SIGINT, SIG_IGN);
    quit_signal = signal(SIGQUIT, SIG_IGN);

    /* Get wallclock start time */
    gettimeofday(&psbox->stat.started, NULL);

    UPDATE_RESULT(psbox, S_RESULT_PD);
    UPDATE_STATUS(psbox, S_STATUS_EXE);

    /* Resume the control logic */
    CLEAR_EVENT(&psbox->ctrl);

    /* Temporary variables. */
    struct rusage initru;
    int waitstatus = 0;
    pid_t waitresult = 0;
    proc_t proc = {0};

    /* System call stack. The prisoner process initially stops at *SYSRET* mode
     * after making the first call to SYS_execve. Therefore, we initialize the
     * stack as it is. */
    int sc_stack[16] = {0, SYS_execve};
    int sc_top = 1;

    /* Make an initial wait to verify the first system call as well as to
     * collect resource usage overhead. */
    waitresult = wait4(pid, &waitstatus, 0, &psbox->stat.ru);

    UPDATE_STATUS(psbox, S_STATUS_BLK);

    /* Save the initial resource usage for further reference */
    memcpy(&initru, &psbox->stat.ru, sizeof(struct rusage));

    /* Clear cache in order to increase timing accuracy */
    flush_cache();
    flush_cache();

    /* Entering the tracing loop */
    do
    {
        /* Trace state refresh of the prisoner program */
        UPDATE_STATUS(psbox, S_STATUS_BLK);

        /* In case nothing happened (possible when the 3rd argument of *wait4*
         * contains the WNOHANG flag), we just go on with next wait(). */
        if (waitresult == 0)
        {
            DBG("wait: nothing happened");
            goto cont;
        }

        /* Figure *net* resource usage (eliminate initru) */
        TIMEVAL_INPLACE_SUBTRACT(psbox->stat.ru.ru_utime, initru.ru_utime);
        TIMEVAL_INPLACE_SUBTRACT(psbox->stat.ru.ru_stime, initru.ru_stime);
        psbox->stat.ru.ru_majflt -= initru.ru_majflt;
        psbox->stat.ru.ru_minflt -= initru.ru_minflt;
        psbox->stat.ru.ru_nswap -= initru.ru_nswap;

        DBG("ru.ru_utime.tv_sec  % 10ld", psbox->stat.ru.ru_utime.tv_sec);
        DBG("ru.ru_utime.tv_usec % 10ld", psbox->stat.ru.ru_utime.tv_usec);
        DBG("ru.ru_stime.tv_sec  % 10ld", psbox->stat.ru.ru_stime.tv_sec);
        DBG("ru.ru_stime.tv_usec % 10ld", psbox->stat.ru.ru_stime.tv_usec);
        DBG("ru.ru_majflt        % 10ld", psbox->stat.ru.ru_majflt);
        DBG("ru.ru_minflt        % 10ld", psbox->stat.ru.ru_minflt);
        DBG("ru.ru_nswap         % 10ld", psbox->stat.ru.ru_nswap);

        /* Raise appropriate events judging each wait status */
        if (WIFSTOPPED(waitstatus))
        {
            DBG("wait: stopped (%d)", WSTOPSIG(waitstatus));
            psbox->stat.signal = WSTOPSIG(waitstatus);
            /* Collect additional information of the prisoner process */
            if (!proc_probe(pid, PROBE_STAT, &proc))
            {
                WARNING("failed to probe the prisoner process");
                kill(-pid, SIGKILL);
                UPDATE_RESULT(psbox, S_RESULT_IE);
                goto done;
            }
            /* Raise appropriate event judging stop signal */
            switch (WSTOPSIG(waitstatus))
            {
            case SIGALRM:       /* real timer expired */
                POST_EVENT(&psbox->ctrl, _QUOTA, S_QUOTA_WALLCLOCK);
                break;
            case SIGXCPU:       /* CPU resource limit exceed */
            case SIGPROF:       /* profile timer expired */
            case SIGVTALRM:     /* virtual timer expired */
                POST_EVENT(&psbox->ctrl, _QUOTA, S_QUOTA_CPU);
                break;
            case SIGMLE:        /* SIGUSR1 used for reporting ML */
                POST_EVENT(&psbox->ctrl, _QUOTA, S_QUOTA_MEMORY);
                break;
            case SIGXFSZ:       /* Output file size exceeded */
                POST_EVENT(&psbox->ctrl, _QUOTA, S_QUOTA_DISK);
                break;
            case SIGTRAP:
                /* Update the tsc instructions counter */
                #ifdef WITH_TSC_COUNTER
                psbox->stat.tsc++;
                DBG("tsc                 %010llu", psbox->stat.tsc);
                #endif /* WITH_TSC_COUNTER */
                /* Collect additional information of prisoner process */
                if (!proc_probe(pid, PROBE_REGS, &proc))
                {
                    WARNING("failed to probe the prisoner process");
                    kill(-pid, SIGKILL);
                    UPDATE_RESULT(psbox, S_RESULT_IE);
                    goto done;
                }

                /* Update sandbox stat with the process runtime info */
                {
                    psbox->stat.vsize = proc.vsize;
                    if (psbox->stat.vsize_peak < proc.vsize)
                    {
                        psbox->stat.vsize_peak = proc.vsize;
                    }
                    psbox->stat.rss = proc.rss * getpagesize();
                }

                /* Detect memory usage against quota */
                if (psbox->stat.vsize_peak > psbox->task.quota[S_QUOTA_MEMORY])
                {
                    kill(-pid, SIGMLE);
                }

                /* For `single step' tracing mode, we have to probe the current
                 * op code (i.e. INT80 for i386 platforms) to tell whether the
                 * prisoner process is invoking a system call. For `system call'
                 * tracing mode, however, every *SIGTRAP* indicates a system
                 * call currently being invoked or just returned. */
                #ifdef WITH_TSC_COUNTER
                if (IS_SYSCALL(&proc) || IS_SYSRET(&proc))
                #endif /* WITH_TSC_COUNTER */
                {
                    int scno = THE_SYSCALL(&proc);
                    if (scno != sc_stack[sc_top])
                    {
                        sc_stack[++sc_top] = scno;
                        psbox->stat.syscall = scno;
                        SET_IN_SYSCALL(&proc);
                        POST_EVENT(&psbox->ctrl, _SYSCALL, scno,
                                                           SYSCALL_ARG1(&proc),
                                                           SYSCALL_ARG2(&proc),
                                                           SYSCALL_ARG3(&proc),
                                                           SYSCALL_ARG4(&proc),
                                                           SYSCALL_ARG5(&proc));
                    }
                    else
                    {
                        CLR_IN_SYSCALL(&proc);
                        sc_stack[sc_top--] = 0;
                        POST_EVENT(&psbox->ctrl, _SYSRET, scno,
                                                          SYSRET_RETVAL(&proc));
                    }
                }
                #ifdef WITH_TSC_COUNTER
                else
                {
                    goto next;
                }
                #endif /* WITH_TSC_COUNTER */
                break;
            default:            /* Other runtime error */
                POST_EVENT(&psbox->ctrl, _SIGNAL, WSTOPSIG(waitstatus));
                break;
            }
        } /* stopped */
        else if (WIFSIGNALED(waitstatus))
        {
            DBG("wait: signaled (%d)", WTERMSIG(waitstatus));
            psbox->stat.signal = WTERMSIG(waitstatus);
            POST_EVENT(&psbox->ctrl, _SIGNAL, WTERMSIG(waitstatus));
        }
        else if (WIFEXITED(waitstatus))
        {
            DBG("wait: exited (%d)", WEXITSTATUS(waitstatus));
            psbox->stat.exitcode = WEXITSTATUS(waitstatus);
            POST_EVENT(&psbox->ctrl, _EXIT, WEXITSTATUS(waitstatus));
        }

        /* Wait for the policy to determine the next action */
        SINK_EVENT(&psbox->ctrl);

        /* Perform the desired action */
        switch (psbox->ctrl.action.type)
        {
        case S_ACTION_CONT:
    next:
            #ifdef WITH_TSC_COUNTER
            if (!trace_next(&proc, TRACE_SINGLE_STEP))
            #else
            if (!trace_next(&proc, TRACE_SYSTEM_CALL))
            #endif /* WITH_TSC_COUNTER */
            {
                WARNING("trace_next");
                kill(-pid, SIGKILL);
                UPDATE_RESULT(psbox, S_RESULT_IE);
                break;
            }
            /* There is no need to update state here! */
            goto cont;          /* Continue with next wait() */
        case S_ACTION_FINI:
            UPDATE_RESULT(psbox, psbox->ctrl.action.data._FINI.result);
            break;
        case S_ACTION_KILL:
            /* Using trace_kill can effectively prevent overrun of undesired
             * behavior, i.e. illegal system call. */
            trace_kill(&proc, SIGKILL);
            UPDATE_RESULT(psbox, psbox->ctrl.action.data._KILL.result);
            break;
        }
        break;                  /* Exiting the tracing loop! */

    cont:
        /* Wait until the prisoner process is trapped  */
        UPDATE_STATUS(psbox, S_STATUS_EXE);
        DBG("----------------------------------------------------------------");
        DBG("wait4(%d,%p,%d,%p)", pid, &waitstatus, 0, &psbox->stat.ru);
        waitresult = waitstatus = 0;
    } while ((waitresult = wait4(pid, &waitstatus, 0, &psbox->stat.ru)) >= 0);

done:
    /* Get wallclock stop time (call a second time to compensate overhead) */
    gettimeofday(&psbox->stat.stopped, NULL);

    UPDATE_STATUS(psbox, S_STATUS_FIN);

    /* Resume the control logic */
    CLEAR_EVENT(&psbox->ctrl);

    DBG("leaving: the tracing thread");

    /* Restore signal handlers */
    signal(SIGTERM, interrupt_signal);
    signal(SIGINT, interrupt_signal);
    signal(SIGQUIT, quit_signal);

    FUNC_RET((void *)&psbox->result, "sandbox_tracer()");
}