feat: 支持killpg和waitid

killpg:给进程组发信号
waitid:等待进程结束
修改测试用例到full里面

Change-Id: Ice058ab4a6eede8ecbaacea0894c2161e3b9dce2
Signed-off-by: wjj <502004968@qq.com>
This commit is contained in:
wjj 2021-08-12 16:16:33 +08:00
parent bbdb977b5e
commit dc3cc094a7
14 changed files with 279 additions and 78 deletions

View File

@ -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();

View File

@ -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

View File

@ -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;
}

View File

@ -33,6 +33,7 @@
#define _LOS_PROCESS_H
#include "los_task.h"
#include <signal.h>
#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);

View File

@ -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);

View File

@ -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);

View File

@ -150,6 +150,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)
@ -258,4 +259,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)
SYSCALL_HAND_DEF(__NR_setrlimit, SysSetrlimit, int, ARG_NUM_2)

View File

@ -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) {

View File

@ -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