首页 > 解决方案 > 如果我在带有 SIGTERM 的 kill() 之后使用 waitpid(),则我的程序不会像预期的那样运行。但是如果我不使用waitpid(),它会起作用吗?

问题描述

我试图关闭一个在子进程上运行的 RPC 客户端上的接收器,给它最大值。5秒完成它的业务。如果我在使用时这样做waitpid()以确保子进程在使用后正常终止SIGTERM,我将无法再使用fork(). 子进程不再使用 execvp() 打开接收器应用程序,而是直接进入应用程序的主菜单。如果我不使用waitpid()而只使用SIGKILLSIGTERM使用该kill()功能,我可以再次重新打开接收器并接收来自调度员的消息。

示例我如何调用方法:sub -> unsub -> sub(如果我在 unsub 方法中使用 waitpid,此 sub 不会重新启动 RPC_Receiver)

订阅方法

void subscribeToDispatcher(CLIENT *clnt) {

    return_code = subscribe_1(NULL, clnt);
    
    if (return_code == NULL) {
        printf("%s\n", PUB_SUB_RET_CODE[UNKNOWN_ERROR]);
    } else {
        printf("Subscribe status: %s\n", PUB_SUB_RET_CODE[*return_code]);
    }
    if (*return_code == OK) {
       
        //receivers childprocess
        printf("Starting the message receiver...\n");
        childPID = fork();
        char *args[] = {};

            if (childPID == 0) {
                execvp("./RPC_Receiver", args);
            }
        if(childPID == -1)
            printf("Error beim starten des Receivers. Fork() Failed.\n");
    }
}

退订方法

void unsubscribeFromDispatcher(CLIENT *clnt) {

    return_code = unsubscribe_1(NULL, clnt);
    
    if (return_code == NULL) {
        printf("%s\n", PUB_SUB_RET_CODE[UNKNOWN_ERROR]);
    } else {
        printf("Unsubscribe status: %s\n", PUB_SUB_RET_CODE[*return_code]);
    }
    
    if (childPID != -1 && childPID != 0 && *return_code == OK) {

        printf("Closing the message receiver");

        kill(childPID, SIGTERM);

        int childDead = 0;
        int status;
        
        for(int i = 0; !childDead && i < 5; i++){

            printf(".");
            fflush(stdout);
            
            if(waitpid(childPID,&status,WNOHANG) == childPID ) {
                childDead = 1;
                printf("\n");
            }
            sleep(1);
        }
        if(!childDead)
            kill(childPID,SIGKILL);
    }
} 

While 循环充当导航,我从主方法调用方法。

 while (1) {
        menuNavigation(input);

        if (strcmp(input, "sub") == 0) {
            subscribeToDispatcher(clnt);
        } else if (strcmp(input, "unsub") == 0) {
            unsubscribeFromDispatcher(clnt);
        } else if (strcmp(input, "publish") == 0) {
            sendMessage(clnt);
        } else if (strcmp(input, "topic") == 0) {
            setTopic(clnt);

        } else if (strcmp(input, "exit") == 0) {
            printf("closing the application.\n");
            unsubscribeFromDispatcher(clnt);
            free(input);
            clnt_destroy(clnt);
            exit(1);
        }
        memset(input, '\0', sizeof(&input));
    }

标签: cforkchild-processkill-processwaitpid

解决方案


感谢@JohnBollinger,我解决了我的问题。我将在此答案中引用他的内容,以便在有人遇到相同问题时更加明显。

字符 *args[] = {}; 不是有效的 C,因为 C 不支持零长度数组或空初始值设定项。此外,即使您的编译器接受它作为扩展,结果也不会是 execvp 的有效输入,无论被执行的程序可能做什么,因为参数列表必须以空指针终止。


推荐阅读