diff --git a/kernel/base/core/los_process.c b/kernel/base/core/los_process.c index 4664ac07..61b463de 100644 --- a/kernel/base/core/los_process.c +++ b/kernel/base/core/los_process.c @@ -133,6 +133,59 @@ STATIC ProcessGroup *OsFindProcessGroup(UINT32 gid) return NULL; } +STATIC INT32 OsSendSignalToSpecifyProcessGroup(ProcessGroup *group, siginfo_t *info, INT32 permission) +{ + INT32 ret, success, err; + LosProcessCB *childCB = NULL; + + success = 0; + ret = -LOS_ESRCH; + LOS_DL_LIST_FOR_EACH_ENTRY(childCB, &(group->processList), LosProcessCB, subordinateGroupList) { + if (childCB->processID == 0) { + continue; + } + + err = OsDispatch(childCB->processID, info, permission); + success |= !err; + ret = err; + } + /* At least one success. */ + return success ? LOS_OK : ret; +} + +LITE_OS_SEC_TEXT INT32 OsSendSignalToAllProcess(siginfo_t *info, INT32 permission) +{ + INT32 ret, success, err; + ProcessGroup *group = NULL; + + success = 0; + err = OsSendSignalToSpecifyProcessGroup(g_processGroup, info, permission); + success |= !err; + ret = err; + /* all processes group */ + LOS_DL_LIST_FOR_EACH_ENTRY(group, &g_processGroup->groupList, ProcessGroup, groupList) { + /* all processes in the process group. */ + err = OsSendSignalToSpecifyProcessGroup(group, info, permission); + success |= !err; + ret = err; + } + return success ? LOS_OK : ret; +} + +LITE_OS_SEC_TEXT INT32 OsSendSignalToProcessGroup(INT32 pid, siginfo_t *info, INT32 permission) +{ + ProcessGroup *group = NULL; + /* Send SIG to all processes in process group PGRP. + If PGRP is zero, send SIG to all processes in + the current process's process group. */ + group = OsFindProcessGroup(pid ? -pid : LOS_GetCurrProcessGroupID()); + if (group == NULL) { + return -LOS_ESRCH; + } + /* all processes in the process group. */ + return OsSendSignalToSpecifyProcessGroup(group, info, permission); +} + STATIC LosProcessCB *OsFindGroupExitProcess(ProcessGroup *group, INT32 pid) { LosProcessCB *childCB = NULL; @@ -1006,12 +1059,19 @@ WAIT_BACK: return LOS_OK; } -STATIC UINT32 OsWaitRecycleChildProcess(const LosProcessCB *childCB, UINT32 intSave, INT32 *status) +STATIC UINT32 OsWaitRecycleChildProcess(const LosProcessCB *childCB, UINT32 intSave, INT32 *status, siginfo_t *info) { ProcessGroup *group = NULL; UINT32 pid = childCB->processID; UINT16 mode = childCB->processMode; INT32 exitCode = childCB->exitCode; + UINT32 uid = 0; + +#ifdef LOSCFG_SECURITY_CAPABILITY + if (childCB->user != NULL) { + uid = childCB->user->userID; + } +#endif OsRecycleZombiesProcess((LosProcessCB *)childCB, &group); SCHEDULER_UNLOCK(intSave); @@ -1023,7 +1083,33 @@ STATIC UINT32 OsWaitRecycleChildProcess(const LosProcessCB *childCB, UINT32 intS *status = exitCode; } } + /* get signal info */ + if (info != NULL) { + siginfo_t tempinfo = { 0 }; + tempinfo.si_signo = SIGCHLD; + tempinfo.si_errno = 0; + tempinfo.si_pid = pid; + tempinfo.si_uid = uid; + /* + * Process exit code + * 31 15 8 7 0 + * | | exit code | core dump | signal | + */ + if ((exitCode & 0x7f) == 0) { + tempinfo.si_code = CLD_EXITED; + tempinfo.si_status = (exitCode >> 8U); + } else { + tempinfo.si_code = (exitCode & 0x80) ? CLD_DUMPED : CLD_KILLED; + tempinfo.si_status = (exitCode & 0x7f); + } + + if (mode == OS_USER_MODE) { + (VOID)LOS_ArchCopyToUser((VOID *)(info), (const VOID *)(&(tempinfo)), sizeof(siginfo_t)); + } else { + (VOID)memcpy_s((VOID *)(info), sizeof(siginfo_t), (const VOID *)(&(tempinfo)), sizeof(siginfo_t)); + } + } (VOID)LOS_MemFree(m_aucSysMem1, group); return pid; } @@ -1057,7 +1143,7 @@ STATIC UINT32 OsWaitOptionsCheck(UINT32 options) return LOS_OK; } -LITE_OS_SEC_TEXT INT32 LOS_Wait(INT32 pid, USER INT32 *status, UINT32 options, VOID *rusage) +STATIC INT32 OsWait(INT32 pid, USER INT32 *status, USER siginfo_t *info, UINT32 options, VOID *rusage) { (VOID)rusage; UINT32 ret; @@ -1066,11 +1152,6 @@ LITE_OS_SEC_TEXT INT32 LOS_Wait(INT32 pid, USER INT32 *status, UINT32 options, V LosProcessCB *processCB = NULL; LosTaskCB *runTask = NULL; - ret = OsWaitOptionsCheck(options); - if (ret != LOS_OK) { - return -ret; - } - SCHEDULER_LOCK(intSave); processCB = OsCurrProcessGet(); runTask = OsCurrTaskGet(); @@ -1082,7 +1163,7 @@ LITE_OS_SEC_TEXT INT32 LOS_Wait(INT32 pid, USER INT32 *status, UINT32 options, V } if (childCB != NULL) { - return (INT32)OsWaitRecycleChildProcess(childCB, intSave, status); + return (INT32)OsWaitRecycleChildProcess(childCB, intSave, status, info); } if ((options & LOS_WAIT_WNOHANG) != 0) { @@ -1105,13 +1186,64 @@ LITE_OS_SEC_TEXT INT32 LOS_Wait(INT32 pid, USER INT32 *status, UINT32 options, V goto ERROR; } - return (INT32)OsWaitRecycleChildProcess(childCB, intSave, status); + return (INT32)OsWaitRecycleChildProcess(childCB, intSave, status, info); ERROR: SCHEDULER_UNLOCK(intSave); return pid; } +LITE_OS_SEC_TEXT INT32 LOS_Wait(INT32 pid, USER INT32 *status, UINT32 options, VOID *rusage) +{ + (VOID)rusage; + UINT32 ret; + + ret = OsWaitOptionsCheck(options); + if (ret != LOS_OK) { + return -ret; + } + + return OsWait(pid, status, NULL, options, NULL); +} + +STATIC UINT32 OsWaitidOptionsCheck(UINT32 options) +{ + UINT32 flag = LOS_WAIT_WNOHANG | LOS_WAIT_WSTOPPED | LOS_WAIT_WCONTINUED | LOS_WAIT_WEXITED | LOS_WAIT_WNOWAIT; + + flag = ~flag & options; + if ((flag != 0) || (options == 0)) { + return LOS_EINVAL; + } + + /* + * only support LOS_WAIT_WNOHANG | LOS_WAIT_WEXITED + * notsupport LOS_WAIT_WSTOPPED | LOS_WAIT_WCONTINUED | LOS_WAIT_WNOWAIT + */ + if ((options & (LOS_WAIT_WSTOPPED | LOS_WAIT_WCONTINUED | LOS_WAIT_WNOWAIT)) != 0) { + return LOS_EOPNOTSUPP; + } + + if (OS_INT_ACTIVE) { + return LOS_EINTR; + } + + return LOS_OK; +} + +LITE_OS_SEC_TEXT INT32 LOS_Waitid(INT32 pid, USER siginfo_t *info, UINT32 options, VOID *rusage) +{ + (VOID)rusage; + UINT32 ret; + + /* check options value */ + ret = OsWaitidOptionsCheck(options); + if (ret != LOS_OK) { + return -ret; + } + + return OsWait(pid, NULL, info, options, NULL); +} + STATIC UINT32 OsSetProcessGroupCheck(const LosProcessCB *processCB, UINT32 gid) { LosProcessCB *runProcessCB = OsCurrProcessGet(); diff --git a/kernel/base/include/los_process_pri.h b/kernel/base/include/los_process_pri.h index c6fa0a83..2edf4b56 100644 --- a/kernel/base/include/los_process_pri.h +++ b/kernel/base/include/los_process_pri.h @@ -408,6 +408,12 @@ STATIC INLINE User *OsCurrUserGet(VOID) * if this option is not specified. */ #define LOS_WAIT_WUNTRACED (1 << 1U) +#define LOS_WAIT_WSTOPPED (1 << 1U) + +/* + * Wait for exited processes + */ +#define LOS_WAIT_WEXITED (1 << 2U) /* * return if a stopped child has been resumed by delivery of SIGCONT. @@ -415,6 +421,12 @@ STATIC INLINE User *OsCurrUserGet(VOID) */ #define LOS_WAIT_WCONTINUED (1 << 3U) +/* + * Leave the child in a waitable state; + * a later wait call can be used to again retrieve the child status information. + */ +#define LOS_WAIT_WNOWAIT (1 << 24U) + /* * Indicates that you are already in a wait state */ @@ -464,6 +476,8 @@ extern UINT32 OsGetKernelInitProcessID(VOID); extern VOID OsSetSigHandler(UINTPTR addr); extern UINTPTR OsGetSigHandler(VOID); extern VOID OsWaitWakeTask(LosTaskCB *taskCB, UINT32 wakePID); +extern INT32 OsSendSignalToProcessGroup(INT32 pid, siginfo_t *info, INT32 permission); +extern INT32 OsSendSignalToAllProcess(siginfo_t *info, INT32 permission); #ifdef __cplusplus #if __cplusplus diff --git a/kernel/base/ipc/los_signal.c b/kernel/base/ipc/los_signal.c index ec7c5d59..71b98b88 100644 --- a/kernel/base/ipc/los_signal.c +++ b/kernel/base/ipc/los_signal.c @@ -351,6 +351,10 @@ static int OsSignalPermissionToCheck(const LosProcessCB *spcb) int OsDispatch(pid_t pid, siginfo_t *info, int permission) { + if (OsProcessIDUserCheckInvalid(pid) || pid < 0) { + return -ESRCH; + } + LosProcessCB *spcb = OS_PCB_FROM_PID(pid); if (OsProcessIsUnused(spcb)) { return -ESRCH; @@ -382,20 +386,27 @@ int OsKill(pid_t pid, int sig, int permission) int ret; /* Make sure that the para is valid */ - if (!GOOD_SIGNO(sig) || pid < 0) { + if (!GOOD_SIGNO(sig)) { return -EINVAL; } - if (OsProcessIDUserCheckInvalid(pid)) { - return -ESRCH; - } /* Create the siginfo structure */ info.si_signo = sig; info.si_code = SI_USER; info.si_value.sival_ptr = NULL; - /* Send the signal */ - ret = OsDispatch(pid, &info, permission); + if (pid > 0) { + /* Send the signal to the specify process */ + ret = OsDispatch(pid, &info, permission); + } else if (pid == -1) { + /* Send SIG to all processes */ + ret = OsSendSignalToAllProcess(&info, permission); + } else { + /* Send SIG to all processes in process group PGRP. + If PGRP is zero, send SIG to all processes in + the current process's process group. */ + ret = OsSendSignalToProcessGroup(pid, &info, permission); + } return ret; } diff --git a/kernel/include/los_process.h b/kernel/include/los_process.h index cc3342ab..ffb834a4 100644 --- a/kernel/include/los_process.h +++ b/kernel/include/los_process.h @@ -33,6 +33,7 @@ #define _LOS_PROCESS_H #include "los_task.h" +#include #ifdef LOSCFG_FS_VFS #include "fs/fd_table.h" @@ -58,6 +59,8 @@ extern UINT32 LOS_GetCurrProcessID(VOID); extern INT32 LOS_Wait(INT32 pid, USER INT32 *status, UINT32 options, VOID *rusage); +extern INT32 LOS_Waitid(INT32 pid, USER siginfo_t *info, UINT32 options, VOID *rusage); + extern INT32 LOS_GetCurrProcessGroupID(VOID); extern INT32 LOS_GetProcessGroupID(UINT32 pid); diff --git a/syscall/los_syscall.h b/syscall/los_syscall.h index 0a7edc1a..b142bf12 100644 --- a/syscall/los_syscall.h +++ b/syscall/los_syscall.h @@ -81,6 +81,7 @@ extern int SysSchedGetPriorityMin(int policy); extern int SysSchedGetPriorityMax(int policy); extern int SysSchedRRGetInterval(int pid, struct timespec *tp); extern int SysWait(int pid, USER int *status, int options, void *rusage); +extern int SysWaitid(idtype_t type, int pid, USER siginfo_t *info, int options, void *rusage); extern int SysFork(void); extern int SysVfork(void); extern unsigned int SysGetPID(void); diff --git a/syscall/process_syscall.c b/syscall/process_syscall.c index 997f631c..3a711662 100644 --- a/syscall/process_syscall.c +++ b/syscall/process_syscall.c @@ -36,6 +36,7 @@ #include "los_sys_pri.h" #include "los_futex_pri.h" #include "los_mp.h" +#include "sys/wait.h" #include "user_copy.h" #include "time.h" #ifdef LOSCFG_SECURITY_CAPABILITY @@ -302,6 +303,42 @@ int SysWait(int pid, USER int *status, int options, void *rusage) return LOS_Wait(pid, status, (unsigned int)options, NULL); } +int SysWaitid(idtype_t type, int pid, USER siginfo_t *info, int options, void *rusage) +{ + (void)rusage; + int ret; + int truepid = 0; + + switch (type) { + case P_ALL: + /* Wait for any child; id is ignored. */ + truepid = -1; + break; + case P_PID: + /* Wait for the child whose process ID matches id */ + if (pid <= 0) { + return -EINVAL; + } + truepid = pid; + break; + case P_PGID: + /* Wait for any child whose process group ID matches id */ + if (pid <= 1) { + return -EINVAL; + } + truepid = -pid; + break; + default: + return -EINVAL; + } + + ret = LOS_Waitid(truepid, info, (unsigned int)options, NULL); + if (ret > 0) { + ret = 0; + } + return ret; +} + int SysFork(void) { return OsClone(0, 0, 0); diff --git a/syscall/syscall_lookup.h b/syscall/syscall_lookup.h index 89bf894e..3afe8dec 100644 --- a/syscall/syscall_lookup.h +++ b/syscall/syscall_lookup.h @@ -151,6 +151,7 @@ SYSCALL_HAND_DEF(__NR_setpriority, SysSetProcessPriority, int, ARG_NUM_3) SYSCALL_HAND_DEF(__NR_setitimer, SysSetiTimer, int, ARG_NUM_3) SYSCALL_HAND_DEF(__NR_getitimer, SysGetiTimer, int, ARG_NUM_2) SYSCALL_HAND_DEF(__NR_wait4, SysWait, int, ARG_NUM_4) +SYSCALL_HAND_DEF(__NR_waitid, SysWaitid, int, ARG_NUM_5) SYSCALL_HAND_DEF(__NR_uname, SysUname, int, ARG_NUM_1) SYSCALL_HAND_DEF(__NR_mprotect, SysMprotect, int, ARG_NUM_3) SYSCALL_HAND_DEF(__NR_getpgid, SysGetProcessGroupID, int, ARG_NUM_1) @@ -259,4 +260,4 @@ SYSCALL_HAND_DEF(__NR_creat_user_thread, SysCreateUserThread, unsigned int, ARG_ SYSCALL_HAND_DEF(__NR_getrusage, SysGetrusage, int, ARG_NUM_2) SYSCALL_HAND_DEF(__NR_sysconf, SysSysconf, long, ARG_NUM_1) SYSCALL_HAND_DEF(__NR_ugetrlimit, SysUgetrlimit, int, ARG_NUM_2) -SYSCALL_HAND_DEF(__NR_setrlimit, SysSetrlimit, int, ARG_NUM_2) \ No newline at end of file +SYSCALL_HAND_DEF(__NR_setrlimit, SysSetrlimit, int, ARG_NUM_2) diff --git a/testsuites/unittest/process/process/BUILD.gn b/testsuites/unittest/process/process/BUILD.gn index 9c8555e8..8923ca0c 100644 --- a/testsuites/unittest/process/process/BUILD.gn +++ b/testsuites/unittest/process/process/BUILD.gn @@ -91,16 +91,11 @@ sources_smoke = [ "smoke/process_test_049.cpp", "smoke/process_test_050.cpp", "smoke/process_test_051.cpp", - "smoke/process_test_053.cpp", - "smoke/process_test_054.cpp", - "smoke/process_test_055.cpp", "smoke/process_test_056.cpp", "smoke/process_test_057.cpp", "smoke/process_test_058.cpp", "smoke/process_test_059.cpp", "smoke/process_test_060.cpp", - "smoke/process_test_061.cpp", - "smoke/process_test_062.cpp", "smoke/process_test_063.cpp", "smoke/process_test_064.cpp", "smoke/process_test_065.cpp", @@ -119,6 +114,11 @@ sources_smoke = [ ] sources_full = [ + "full/process_test_053.cpp", + "full/process_test_054.cpp", + "full/process_test_055.cpp", + "full/process_test_061.cpp", + "full/process_test_062.cpp", ] if (LOSCFG_USER_TEST_LEVEL >= TEST_LEVEL_LOW) { diff --git a/testsuites/unittest/process/process/smoke/process_test_053.cpp b/testsuites/unittest/process/process/full/process_test_053.cpp similarity index 100% rename from testsuites/unittest/process/process/smoke/process_test_053.cpp rename to testsuites/unittest/process/process/full/process_test_053.cpp diff --git a/testsuites/unittest/process/process/smoke/process_test_054.cpp b/testsuites/unittest/process/process/full/process_test_054.cpp similarity index 100% rename from testsuites/unittest/process/process/smoke/process_test_054.cpp rename to testsuites/unittest/process/process/full/process_test_054.cpp diff --git a/testsuites/unittest/process/process/smoke/process_test_055.cpp b/testsuites/unittest/process/process/full/process_test_055.cpp similarity index 100% rename from testsuites/unittest/process/process/smoke/process_test_055.cpp rename to testsuites/unittest/process/process/full/process_test_055.cpp diff --git a/testsuites/unittest/process/process/smoke/process_test_061.cpp b/testsuites/unittest/process/process/full/process_test_061.cpp similarity index 100% rename from testsuites/unittest/process/process/smoke/process_test_061.cpp rename to testsuites/unittest/process/process/full/process_test_061.cpp diff --git a/testsuites/unittest/process/process/smoke/process_test_062.cpp b/testsuites/unittest/process/process/full/process_test_062.cpp similarity index 100% rename from testsuites/unittest/process/process/smoke/process_test_062.cpp rename to testsuites/unittest/process/process/full/process_test_062.cpp diff --git a/testsuites/unittest/process/process/process_process_test.cpp b/testsuites/unittest/process/process/process_process_test.cpp index c2f6da61..4f602173 100644 --- a/testsuites/unittest/process/process/process_process_test.cpp +++ b/testsuites/unittest/process/process/process_process_test.cpp @@ -610,40 +610,6 @@ HWTEST_F(ProcessProcessTest, ItTestProcess051, TestSize.Level0) ItTestProcess051(); } -/* * - * @tc.name: it_test_process_053 - * @tc.desc: function for killpg:Sends a signal to the process group, - * Other processes in the process group can receive the signal. - * @tc.type: FUNC - * @tc.require: AR000E0QAB - */ -HWTEST_F(ProcessProcessTest, ItTestProcess053, TestSize.Level0) -{ - ItTestProcess053(); -} - -/* * - * @tc.name: it_test_process_054 - * @tc.desc: function for waitid: The waitid parameter is incorrect and the error code is verified. - * @tc.type: FUNC - * @tc.require: AR000E0QAB - */ -HWTEST_F(ProcessProcessTest, ItTestProcess054, TestSize.Level0) -{ - ItTestProcess054(); -} - -/* * - * @tc.name: it_test_process_055 - * @tc.desc: function for waitid:To test the function of transferring different parameters of the waitid. - * @tc.type: FUNC - * @tc.require: AR000E0QAB - */ -HWTEST_F(ProcessProcessTest, ItTestProcess055, TestSize.Level0) -{ - ItTestProcess055(); -} - /* * * @tc.name: it_test_process_056 * @tc.desc: function for posix_spawn:Verifying Basic Functions @@ -700,29 +666,6 @@ HWTEST_F(ProcessProcessTest, ItTestProcess060, TestSize.Level0) ItTestProcess060(); } -/* * - * @tc.name: it_test_process_061 - * @tc.desc: function for killpg: The killpg parameter is incorrect and the error code is verified. - * @tc.type: FUNC - * @tc.require: AR000E0QAB - */ -HWTEST_F(ProcessProcessTest, ItTestProcess061, TestSize.Level0) -{ - ItTestProcess061(); -} - -/* * - * @tc.name: it_test_process_062 - * @tc.desc: function for killpg:Fork two processes. The killpg sends a signal to the current process group. - * The other two processes can receive the signal. - * @tc.type: FUNC - * @tc.require: AR000E0QAB - */ -HWTEST_F(ProcessProcessTest, ItTestProcess062, TestSize.Level0) -{ - ItTestProcess062(); -} - /* * * @tc.name: it_test_process_063 * @tc.desc: function for posix_spawn: The file path, argv command, and envp environment variable are invalid. @@ -893,4 +836,63 @@ HWTEST_F(ProcessProcessTest, ItTestProcessSmp008, TestSize.Level0) } #endif #endif + +#if defined(LOSCFG_USER_TEST_FULL) +/* * + * @tc.name: it_test_process_053 + * @tc.desc: function for killpg:Sends a signal to the process group, + * Other processes in the process group can receive the signal. + * @tc.type: FUNC + * @tc.require: AR000E0QAB + */ +HWTEST_F(ProcessProcessTest, ItTestProcess053, TestSize.Level0) +{ + ItTestProcess053(); +} + +/* * + * @tc.name: it_test_process_054 + * @tc.desc: function for waitid: The waitid parameter is incorrect and the error code is verified. + * @tc.type: FUNC + * @tc.require: AR000E0QAB + */ +HWTEST_F(ProcessProcessTest, ItTestProcess054, TestSize.Level0) +{ + ItTestProcess054(); +} + +/* * + * @tc.name: it_test_process_055 + * @tc.desc: function for waitid:To test the function of transferring different parameters of the waitid. + * @tc.type: FUNC + * @tc.require: AR000E0QAB + */ +HWTEST_F(ProcessProcessTest, ItTestProcess055, TestSize.Level0) +{ + ItTestProcess055(); +} + +/* * + * @tc.name: it_test_process_061 + * @tc.desc: function for killpg: The killpg parameter is incorrect and the error code is verified. + * @tc.type: FUNC + * @tc.require: AR000E0QAB + */ +HWTEST_F(ProcessProcessTest, ItTestProcess061, TestSize.Level0) +{ + ItTestProcess061(); +} + +/* * + * @tc.name: it_test_process_062 + * @tc.desc: function for killpg:Fork two processes. The killpg sends a signal to the current process group. + * The other two processes can receive the signal. + * @tc.type: FUNC + * @tc.require: AR000E0QAB + */ +HWTEST_F(ProcessProcessTest, ItTestProcess062, TestSize.Level0) +{ + ItTestProcess062(); +} +#endif } // namespace OHOS