Exemple #1
0
int main()
{
    struct Process *child;
    
    struct TagItem tags[] =
    {
	{ NP_Entry,         (IPTR) entry              },
    	{ NP_Cli,           (IPTR) TRUE               },
        { NP_Name,          (IPTR) "test"             },
        { NP_NotifyOnDeath, (IPTR) TRUE               },
        { TAG_DONE,         0                         }
    };
    
    child = CreateNewProc(tags);
    
    if(child)
    {
	ULONG childid = GetETask((struct Task*) child)->et_UniqueID;
	Printf("Waiting for child with id %d\n", childid);
	ChildWait(childid);
	Printf("Child exited, freeing child\n");
	ChildFree(childid);
    }
    else
	PrintFault(IoErr(), "Couldn't create child process");
    return 0;
}
Exemple #2
0
IPTR TaskGetStorageSlot(struct Task * t, LONG id)
{
    struct ETask *et = t ? GetETask(t) : NULL;
    IPTR *ts;

    D(bug("TaskGetStorageSlot: %p: Get TaskGetStorageSlot %d\n", et, id);)

    if (!et) {
Exemple #3
0
int main()
{
    tmpname = mktemp("T:flockXXXXXX");
    int fd = open(tmpname, O_CREAT);
    TEST((fd != -1));

    TEST((flock(fd, LOCK_SH|LOCK_NB) == 0));
    TEST((flock(fd, LOCK_UN) == 0));

    TEST((flock(fd, LOCK_EX|LOCK_NB) == 0));
    TEST((flock(fd, LOCK_UN) == 0));

    TEST((flock(fd, LOCK_SH) == 0));
    TEST((flock(fd, LOCK_UN) == 0));

    TEST((flock(fd, LOCK_EX) == 0));
    TEST((flock(fd, LOCK_UN) == 0));

    close(fd);

    /* Create NPROCS processes increasing counter ITERATIONS times in an ugly 
       way */
    int counter = 0;
    struct Process *procs[NPROCS];
    ULONG ids[NPROCS];
    struct TagItem tags[] =
    {
	{ NP_Entry,         (IPTR) entry     },
        { NP_Name,          (IPTR) "flocker" },
        { NP_Output,        (IPTR) Output()  },
        { NP_CloseOutput,   (IPTR) FALSE     },
        { NP_UserData,      (IPTR) &counter  },
        { NP_NotifyOnDeath, (IPTR) TRUE      },
        { TAG_DONE,         0                }
    };

    int i;
    InitSemaphore(&sem);
    for(i = 0; i < NPROCS; i++)
    {
	procs[i] = CreateNewProc(tags);
	TEST((procs[i]));
	ids[i] = GetETask(procs[i])->et_UniqueID;
	Signal((struct Task *)procs[i], SIGBREAKF_CTRL_C);
    }
    
    for(i = 0; i < NPROCS; i++)
    {
	ChildWait(ids[i]);
	ChildFree(ids[i]);
    }
    putchar('\n');
    
    TEST((counter == NPROCS * ITERATIONS));
    
    cleanup();
    return OK;
}
Exemple #4
0
int main()
{
    struct Process *child;
    
    struct TagItem tags[] =
    {
	{ NP_Entry,         (IPTR) entry              },
    	{ NP_Cli,           (IPTR) TRUE               },
        { NP_Name,          (IPTR) "test"             },
        { NP_NotifyOnDeath, (IPTR) TRUE               },
        { TAG_DONE,         0                         }
    };
    
    child = CreateNewProc(tags);
    
    if(child)
    {
	ULONG childstatus;
	ULONG childid = GetETask((struct Task*) child)->et_UniqueID;
	Printf("Checking status value for non-existing child id\n");
	childstatus = ChildStatus(-1);
	assert(childstatus == CHILD_NOTFOUND);
	Printf("Result: CHILD_NOTFOUND\n");
	Printf("Checking status value for running child id\n");
	childstatus = ChildStatus(childid);
	assert(childstatus == CHILD_ACTIVE);
	Printf("Result: CHILD_ACTIVE\n");
	ChildWait(childid);
	Printf("Checking status value for died child id\n");
	childstatus = ChildStatus(childid);
	assert(childstatus == CHILD_EXITED);
	Printf("Result: CHILD_EXITED\n");
	ChildFree(childid);
	Printf("Checking status value for freed child id\n");
	childstatus = ChildStatus(childid);
	assert(childstatus == CHILD_NOTFOUND);
	Printf("Result: CHILD_NOTFOUND\n");
    }
    else
	PrintFault(IoErr(), "Couldn't create child process");
    return 0;
}
Exemple #5
0
    EXAMPLE

    BUGS

    SEE ALSO

    INTERNALS

*****************************************************************************/
{
    AROS_LIBFUNC_INIT

    struct Task *this = FindTask(NULL);
    struct ETask *et, *child;

    et = GetETask(this);
    if(et == NULL)
	return CHILD_NOTNEW;

    if(tid == 0L)
    {
	ForeachNode(&et->et_Children, child)
	{
	    /*
		Don't need to Remove(), because I'll blow away the entire
		list at the end of the loop.
	     */
	    child->et_Parent = NULL;
	}
	NEWLIST(&et->et_Children);
    }
Exemple #6
0
    EXAMPLE

    BUGS

    SEE ALSO
        RestoreTaskStorage()

    INTERNALS

******************************************************************************/
{
    AROS_LIBFUNC_INIT

    struct Task *ThisTask = GET_THIS_TASK;
    struct ETask *et = ThisTask ? GetETask(ThisTask) : NULL;
    IPTR *taskstorage, *tsout;
    IPTR slots;
    
    if (!et || et->et_TaskStorage == NULL)
        return NULL;

    taskstorage = et->et_TaskStorage;
    slots = taskstorage[__TS_FIRSTSLOT];

    /* NOTE: Saved task storage *must not* be passed around
     *       to another task! This is why it is not MEMF_PUBLIC.
     */
    tsout = AllocMem(slots * sizeof(tsout[0]), MEMF_ANY);
    if (tsout) {
        CopyMemQuick(taskstorage, tsout, slots * sizeof(tsout[0]));
Exemple #7
0
        pid_t waitpid(

/*  SYNOPSIS */
        pid_t pid,
        int *status,
        int options)

/*  FUNCTION
        Waits for child process with given process id to change state. State
        change is one of the following events: child has exited, child was
        terminated by a signal, child was stopped by a signal, child was
        resumed by a signal.
        
        The function stores status of the process that changed state in the
        pointer given as status argument.

        The following macros can be used to extract information from the
        status value:

        WIFEXITED(status)    - true if the process has exited
        WEXITSTATUS(status)  - exit status of the exited process
        WIFSIGNALED(status)  - true if the child process was terminated by a
                               signal
        WTERMSIG(status)     - number of the signal that caused process
                               termination
        WIFSTOPPED(status)   - true if the child process was stopped by a
                               signal
        WSTOPSIG(status)     - number of the signal that caused child process
                               stop
        WIFCONTINUED(status) - true if the child process was resumed by the
                               SIGCONT signal.

        Unless WNOHANG option is set, parent process will be suspended until a
        child changes state. If a child process has already changed state,
        function returns immediately.

    INPUTS
        pid - Process id of the process you want to wait for or -1 to wait for
                any child process
        status - Pointer to int where child status will be stored or NULL if
                you don't want to store status.
        options - ORed zero or more of the following constants:
        
            WNOHANG - return immediately if no child process changed state

    RESULT
        Process id of the child process on success or -1 on error. If an error
        occurred, the global variable errno is set.

    NOTES
        This function will work only for child processeses notifying parent
        process of their death, for example processes created by vfork() call.
        If you want to use it for other processes, remember to set the
        NP_NotifyOnDeath tag value to TRUE during child process creation.

    EXAMPLE

    BUGS

    SEE ALSO
        wait()

    INTERNALS
        Since POSIX signals are not yet implemented, WIFSIGNALED, WIFSTOPPED
        and WIFCONTINUED macros always return 0. WIFEXITED always returns 1.

        The et_UniqueID field of the ETask structure is used as process id.

******************************************************************************/
{
    struct ETask *et;
    ULONG tid = pid;
    pid_t ret = -1;
    int exchildno;

    D(bug("waitpid(%d, %p, %d)\n", pid, status, options));

    et = GetETask(FindTask(NULL));
    if(!et)
    {
        /* only ETasks are fertile */
        errno = ECHILD;
        return -1;
    }
    
    if (pid < -1 || pid == 0)
    {
        /* process groups not yet supported */
        errno = EINVAL;
        return -1;
    }

    if (pid == -1)
        tid = 0;

    if(tid != 0 && ChildStatus(tid) == CHILD_NOTFOUND)
    {
        /* error if there's no such child */
        errno = ECHILD;
        return -1;
    }

    if (options & ~WNOHANG)
    {
        /* option not yet supported */
        errno = EINVAL;
        return -1;
    }
    
    /* not very pretty, perhaps we need a function for counting dead 
       children? */
    ListLength(&et->et_TaskMsgPort.mp_MsgList, exchildno);
    if ((options & WNOHANG) && (
        (tid != 0 && ChildStatus(tid) != CHILD_EXITED) ||
        (tid == 0 && exchildno == 0)
    ))
    {
        D(bug("waitpid: no dead children\n"));
        /* no dead children atm */
        return 0;
    }

    D(bug("waitpid: wait for %d to die\n", tid));
    et = (struct ETask *)ChildWait(tid);
    if (et != (struct ETask *)CHILD_NOTNEW)
    {
        if(status)
        {
            *status = et->et_Result1;
        }
        ret = et->et_UniqueID;
        ChildFree(et->et_UniqueID);
    }
    else
        errno = ECHILD;
    
    D(bug("waitpid: leaving (%d)\n", ret));

    return ret;
}
Exemple #8
0
LONG launcher()
{
    D(bug("launcher: Entered child launcher\n"));

    struct Task *this = FindTask(NULL);
    struct vfork_data *udata = this->tc_UserData;
    BYTE child_signal;
    struct Library *aroscbase = NULL;

    GetIntETask(this)->iet_startup = GetETask(this)->et_Result2 = AllocVec(sizeof(struct aros_startup), MEMF_ANY | MEMF_CLEAR);

    /* Allocate signal for parent->child communication */
    child_signal = udata->child_signal = AllocSignal(-1);
    D(bug("launcher: Allocated child signal: %d\n", udata->child_signal));
    if(udata->child_signal == -1)
    {
	/* Lie */
	udata->child_errno = ENOMEM;
	Signal(udata->parent, 1 << udata->parent_signal);
	return -1;
    }

    if(__register_init_fdarray(udata->ppriv->acpd_fd_array, udata->ppriv->acpd_numslots))
        aroscbase = OpenLibrary((STRPTR) "arosc.library", 0);
    if(!aroscbase)
    {
	FreeSignal(child_signal);
	udata->child_errno = ENOMEM;
	Signal(udata->parent, 1 << udata->parent_signal);
	return -1;	
    }
    
    udata->cpriv = __get_arosc_privdata();
    udata->cpriv->acpd_parent_does_upath = udata->ppriv->acpd_doupath;
    udata->cpriv->acpd_flags |= DO_NOT_CLONE_ENV_VARS;

    if(setjmp(__aros_startup_jmp_buf) == 0)
    {
        /* Setup complete, signal parent */
        D(bug("launcher: Signaling parent that we finished setup\n"));
        Signal(udata->parent, 1 << udata->parent_signal);

        D(bug("launcher: Child waiting for exec or exit\n"));
        Wait(1 << udata->child_signal);

        if(udata->child_executed)
        {
            APTR exec_id;
            BPTR dir;
            
            D(bug("launcher: child executed\n"));
            
            /* Set current dir to parent's current dir */
            dir = DupLock(((struct Process *)udata->parent)->pr_CurrentDir);
            UnLock(CurrentDir(dir));
            /* Don't mind updating aroscbase->acb_startup_cd_changed as we will
               exit from process after __exec_do has finished */

            /* Filenames passed from parent obey parent's __doupath */
            __doupath = udata->cpriv->acpd_parent_does_upath;
            D(bug("launcher: __doupath == %d for __exec_prepare()\n", __doupath));
            
            exec_id = udata->exec_id = __exec_prepare(
                udata->exec_filename,
                udata->exec_searchpath,
                udata->exec_argv,
                udata->exec_envp
            );
            
            udata->child_errno = errno;

            /* Clear __doupath again, command will set it if wanted */
            __doupath = 0;
            
            D(bug("launcher: informing parent that we have run __exec_prepare\n"));
            /* Inform parent that we have run __exec_prepare */
            Signal(udata->parent, 1 << udata->parent_signal);
            
            /* Wait 'till __exec_do() is called on parent process */
            D(bug("launcher: Waiting parent to get the result\n"));
            Wait(1 << udata->child_signal);

            D(bug("launcher: informing parent that we won't use udata anymore\n"));
            /* Inform parent that we won't use udata anymore */
            Signal(udata->parent, 1 << udata->parent_signal);

            if (exec_id)
            {
                D(bug("launcher: executing command\n"));
                __exec_do(exec_id);
                
                assert(0); /* Should not be reached */
            }
            else
            {
                D(bug("launcher: exit because execve returned with an error\n"));
                _exit(0);
            }
        }
        else
        {
            D(bug("launcher: informing parent that we won't use udata anymore\n"));
            /* Inform parent that we won't use udata anymore */
            Signal(udata->parent, 1 << udata->parent_signal);
        }
    }
    else
    {
        D(bug("launcher: freeing child_signal\n"));
        FreeSignal(child_signal);
        CloseLibrary(aroscbase);
    }
    
    return 0;
}
Exemple #9
0
	pid_t wait(

/*  SYNOPSIS */
	int *status)

/*  FUNCTION
	Waits for child process to change state. State change is one of the
	following events: child has exited, child was terminated by a signal,
	child was stopped by a signal, child was resumed by a signal.
	
	The function stores status of the process that changed state in the
	pointer given as status argument.

	The following macros can be used to extract information from the
	status value:

	WIFEXITED(status)    - true if the process has exited
	WEXITSTATUS(status)  - exit status of the exited process
	WIFSIGNALED(status)  - true if the child process was terminated by a
	                       signal
	WTERMSIG(status)     - number of the signal that caused process
	                       termination
	WIFSTOPPED(status)   - true if the child process was stopped by a
	                       signal
	WSTOPSIG(status)     - number of the signal that caused child process
	                       stop
	WIFCONTINUED(status) - true if the child process was resumed by the
	                       SIGCONT signal.
	
	Parent process will be suspended until a child changes state. If a
	child process has already changed state, function returns immediately.

    INPUTS
	status - Pointer to int where child return status will be stored or
	NULL if you don't want to store status.

    RESULT
	Process id of the child process on success or -1 on error. If an error
	occurred, the global variable errno is set.

    NOTES
	This function will work only for child processeses notifying parent
	process of their death, for example processes created by vfork() call.
	If you want to use it for other processes, remember to set the
	NP_NotifyOnDeath tag value to TRUE during child process creation.

    EXAMPLE

    BUGS

    SEE ALSO
	waitpid()

    INTERNALS
	Since POSIX signals are not yet implemented, WIFSIGNALED, WIFSTOPPED
	and WIFCONTINUED macros always return 0. WIFEXITED always returns 1.

	The et_UniqueID field of the ETask structure is used as process id.

******************************************************************************/
{
    pid_t ret = -1;
    struct ETask *et;

    D(bug("wait()\n"));

    et = GetETask(FindTask(NULL));
    if(!et)
    {
	/* only ETasks are fertile */
	errno = ECHILD;
	return -1;
    }

    et = (struct ETask *)ChildWait(0);
    if (et != CHILD_NOTNEW)
    {
	if(status && IntETask(et)->iet_startup)
	{
	    struct aros_startup *startup = IntETask(et)->iet_startup;
	    *status = startup->as_startup_error;
	}
        ret = et->et_UniqueID;
        ChildFree(et->et_UniqueID);
    }
    else
	errno = ECHILD;

    return ret;
}