Use SIGCHLD with waitpid(); implemented wait() and waitid()

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5515 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2013-01-13 18:53:00 +00:00
parent 77960c8ca8
commit 65c2f3e7ff
5 changed files with 307 additions and 19 deletions

View File

@ -464,4 +464,5 @@
* apps/exampes/posix_spawn: Added a test of poxis_spawn().
* apps/examples/ostest: Extend signal handler test to catch
death-of-child signals (SIGCHLD).
* apps/examples/ostest/waitpid.c: Add a test for waitpid(), waitid(),
and wait().

View File

@ -52,6 +52,10 @@ ifeq ($(CONFIG_ARCH_FPU),y)
CSRCS += fpu.c
endif
ifeq ($(CONFIG_SCHED_WAITPID),y)
CSRCS += waitpid.c
endif
ifneq ($(CONFIG_DISABLE_PTHREAD),y)
CSRCS += cancel.c cond.c mutex.c sem.c barrier.c
ifneq ($(CONFIG_RR_INTERVAL),0)

View File

@ -105,68 +105,74 @@
/* dev_null.c ***************************************************************/
extern int dev_null(void);
int dev_null(void);
/* fpu.c ********************************************************************/
extern void fpu_test(void);
void fpu_test(void);
/* waitpid.c ****************************************************************/
#ifdef CONFIG_SCHED_WAITPID
int waitpid_test(void);
#endif
/* mutex.c ******************************************************************/
extern void mutex_test(void);
void mutex_test(void);
/* rmutex.c ******************************************************************/
extern void recursive_mutex_test(void);
void recursive_mutex_test(void);
/* sem.c ********************************************************************/
extern void sem_test(void);
void sem_test(void);
/* cond.c *******************************************************************/
extern void cond_test(void);
void cond_test(void);
/* mqueue.c *****************************************************************/
extern void mqueue_test(void);
void mqueue_test(void);
/* timedmqueue.c ************************************************************/
extern void timedmqueue_test(void);
void timedmqueue_test(void);
/* cancel.c *****************************************************************/
extern void cancel_test(void);
void cancel_test(void);
/* timedwait.c **************************************************************/
extern void timedwait_test(void);
void timedwait_test(void);
/* sighand.c ****************************************************************/
extern void sighand_test(void);
void sighand_test(void);
/* posixtimers.c ************************************************************/
extern void timer_test(void);
void timer_test(void);
/* roundrobin.c *************************************************************/
extern void rr_test(void);
void rr_test(void);
/* barrier.c ****************************************************************/
extern void barrier_test(void);
void barrier_test(void);
/* prioinherit.c ************************************************************/
extern void priority_inheritance(void);
void priority_inheritance(void);
/* vfork.c ******************************************************************/
#ifdef CONFIG_ARCH_HAVE_VFORK
extern int vfork_test(void);
int vfork_test(void);
#endif
/* APIs exported (conditionally) by the OS specifically for testing of
@ -174,8 +180,8 @@ extern int vfork_test(void);
*/
#if defined(CONFIG_DEBUG) && defined(CONFIG_PRIORITY_INHERITANCE) && defined(CONFIG_SEM_PHDEBUG)
extern void sem_enumholders(FAR sem_t *sem);
extern int sem_nfreeholders(void);
void sem_enumholders(FAR sem_t *sem);
int sem_nfreeholders(void);
#else
# define sem_enumholders(sem)
# define sem_nfreeholders()

View File

@ -301,6 +301,14 @@ static int user_main(int argc, char *argv[])
check_test_memory_usage();
#endif
#ifdef CONFIG_SCHED_WAITPID
/* Check waitpid() and friends */
printf("\nuser_main: waitpid test\n");
waitpid_test();
check_test_memory_usage();
#endif
#ifndef CONFIG_DISABLE_PTHREAD
/* Verify pthreads and pthread mutex */

269
examples/ostest/waitpid.c Normal file
View File

@ -0,0 +1,269 @@
/****************************************************************************
* examples/ostest/waitpid.c
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/wait.h>
#include <stdbool.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include "ostest.h"
#ifdef CONFIG_SCHED_WAITPID
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define RETURN_STATUS 14
#define NCHILDREN 3
#define PRIORITY 100
/****************************************************************************
* Private Data
****************************************************************************/
static int g_waitpids[NCHILDREN];
/****************************************************************************
* Priviate Functions
****************************************************************************/
static int waitpid_main(int argc, char *argv[])
{
pid_t me = getpid();
printf("waitpid_main: PID %d Started\n", me);
sleep(3);
printf("waitpid_main: PID %d exitting with result=%d\n", me, RETURN_STATUS);
return RETURN_STATUS;
}
static void waitpid_start_children(void)
{
int ret;
int i;
for (i = 0; i < NCHILDREN; i++)
{
ret = TASK_CREATE("waitpid", PRIORITY, STACKSIZE, waitpid_main, NULL);
if (ret < 0)
{
printf("waitpid_start_child: ERROR Failed to start user_main\n");
}
else
{
printf("waitpid_start_child: Started waitpid_main at PID=%d\n", ret);
}
g_waitpids[i] = ret;
}
}
static void waitpid_last(void)
{
int stat_loc;
int ret;
printf("waitpid_last: Waiting for PID=%d with waitpid()\n",
g_waitpids[NCHILDREN-1]);
ret = (int)waitpid(g_waitpids[NCHILDREN-1], &stat_loc, 0);
if (ret < 0)
{
int errcode = errno;
printf("waitpid_last: ERROR: PID %d waitpid failed: %d\n",
g_waitpids[NCHILDREN-1], errcode);
}
else if (stat_loc != RETURN_STATUS)
{
printf("waitpid_last: ERROR: PID %d return status is %d, expected %d\n",
g_waitpids[NCHILDREN-1], stat_loc, RETURN_STATUS);
}
else
{
printf("waitpid_last: PID %d waitpid succeeded with stat_loc=%d\n",
g_waitpids[NCHILDREN-1], stat_loc);
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
int waitpid_test(void)
{
#ifdef CONFIG_SCHED_HAVE_PARENT
siginfo_t info;
#endif
int stat_loc;
int ret;
/* Start the children and wait for first one to complete */
printf("\nTest waitpid()\n");
waitpid_start_children();
printf("waitpid_test: Waiting for PID=%d with waitpid()\n", g_waitpids[0]);
ret = (int)waitpid(g_waitpids[0], &stat_loc, 0);
if (ret < 0)
{
int errcode = errno;
printf("waitpid_test: ERROR: PID %d waitpid failed: %d\n",
g_waitpids[0], errcode);
}
else if (ret != g_waitpids[0])
{
printf("waitpid_test: ERROR: PID %d wait returned PID %d\n",
g_waitpids[0], ret);
}
else if (stat_loc != RETURN_STATUS)
{
printf("waitpid_test: ERROR: PID %d return status is %d, expected %d\n",
g_waitpids[0], stat_loc, RETURN_STATUS);
}
else
{
printf("waitpid_test: PID %d waitpid succeeded with stat_loc=%d\n",
g_waitpids[0], stat_loc);
}
/* Wait a big to make sure that the other threads complete */
waitpid_last();
sleep(1);
#ifdef CONFIG_SCHED_HAVE_PARENT
/* Start the children and wait for first one to complete */
printf("\nTest waitid(P_PID)\n");
waitpid_start_children();
printf("waitpid_test: Waiting for PID=%d with waitid()\n", g_waitpids[0]);
ret = waitid(P_PID, (id_t)g_waitpids[0], &info, WEXITED);
if (ret < 0)
{
int errcode = errno;
printf("waitpid_test: ERROR: PID %d waitid failed: %d\n",
g_waitpids[0], errcode);
}
else if (info.si_pid != g_waitpids[0])
{
printf("waitpid_test: ERROR: PID %d waitid returned PID %d\n",
g_waitpids[0], info.si_pid);
}
else if (info.si_status != RETURN_STATUS)
{
printf("waitpid_test: ERROR: PID %d return status is %d, expected %d\n",
info.si_pid, info.si_status, RETURN_STATUS);
}
else
{
printf("waitpid_test: waitid PID %d succeeded with si_status=%d\n",
info.si_pid, info.si_status);
}
/* Wait a big to make sure that the other threads complete */
waitpid_last();
sleep(1);
/* Start the children and wait for any one to complete */
printf("\nTest waitid(P_ALL)\n");
waitpid_start_children();
printf("waitpid_test: Waiting for any child with waitid()\n");
ret = waitid(P_ALL, 0, &info, WEXITED);
if (ret < 0)
{
int errcode = errno;
printf("waitpid_test: ERROR: waitid failed: %d\n", errcode);
}
else if (info.si_status != RETURN_STATUS)
{
printf("waitpid_test: ERROR: PID %d return status is %d, expected %d\n",
info.si_pid, info.si_status, RETURN_STATUS);
}
else
{
printf("waitpid_test: PID %d waitid succeeded with si_status=%d\n",
info.si_pid, info.si_status);
}
/* Wait a big to make sure that the other threads complete */
waitpid_last();
sleep(1);
/* Start the children and wait for first one to complete */
printf("\nTest wait()\n");
waitpid_start_children();
printf("waitpid_test: Waiting for any child with wait()\n");
ret = (int)wait(&stat_loc);
if (ret < 0)
{
int errcode = errno;
printf("waitpid_test: ERROR: wait failed: %d\n", errcode);
}
else if (stat_loc != RETURN_STATUS)
{
printf("waitpid_test: ERROR: PID %d return status is %d, expected %d\n",
ret, stat_loc, RETURN_STATUS);
}
else
{
printf("waitpid_test: PID %d wait succeeded with stat_loc=%d\n",
ret, stat_loc);
}
/* Wait a big to make sure that the other threads complete */
waitpid_last();
sleep(1);
#endif
return 0;
}
#endif /* CONFIG_SCHED_WAITPID */