Home > Mobile >  how to make process not run in background?
how to make process not run in background?

Time:11-10

I am not English user, so there can be some wrong sentences:)

I am making minishell. In code, child process runs execvp function. And parent process change child's pgid to be same with child's pid.

However, after change child's pgid, child begin to run in background, so minishell doesn't work well. If I don't change child's pgid, then it works perfectly.

I want to know how to bring background child process to foreground, or how not to make child run in background.

int execute(){
    pid_t pid = fork();
    if (pid == 0){
        execvp(args[idx], &args[idx]);
    }
    else{
        setpgid(pid, pid);
        
        int status;
        waitpid(pid, &status, WUNTRACED);
        if (WIFSTOPPED(status))
            kill(pid, SIGINT);
    }
}

CodePudding user response:

TL;DR: use tcsetpgrp() to change which process group is in the foreground on the relevant terminal.


At any given time, a terminal has at most one controlling process group. Processes in this process group can receive input from the terminal and write output to it, and they receive certain signals generated by the terminal driver in response to keystrokes such as ctrl-C. Being in its controlling terminal's controlling process group is what it means for a process to be in the foreground.

Processes in other process groups do not receive input from the terminal and cannot write output to it. They will receive different signals from the terminal driver, under different circumstances, than processes in the controlling process group do. This is what it means to be in the background.

A shell that performs job control, which includes, but is not limited to, managing foreground and background status for other processes, does so in part by assigning the processes it spawns to appropriate process groups (setpgid()) and managing which one, including its own, is the foreground process group at any given time (tcsetpgrp()). This is much more complicated than simply running all jobs in its own process group.

The Glibc manual contains quite a lot of information about this area, including example code. Consider reading the chapter Job Control, and especially its section Implementing a Job Control Shell.

CodePudding user response:

Thanks to help from others, I made sample code that runs bc command continuously until I enter '1'.

In this code, I use tcsetpgrp() to give child the control of terminal.

bc command works well. However, when I enter 'quit', child process receives SIGSTP and code is ended. (What I want is continuing while loop!!)

int main()
{
    while(1){
        int n;
        scanf("%d", &n);
        execute();
        if (n == 1)
            break;
    }
}

void execute()
{
    char *args[] = {"bc", 0};
    pid_t pid = fork();
    if (pid == 0){
        execvp("bc", args);
    }
    if (pid > 0){
        setpgid(pid, pid);
        tcsetpgrp(STDIN_FILENO, getpgid(pid);
        wait(0);
    }
}

I think that I should change child to background and parent to foreground after execvp. However, after execvp function, child process terminates, so it seems possible to do that.

So, I also added

signal(SIGSTP, handler);

where handler function is

void handler(int sig){
    tcsetpgrp(STDIN_FILENO, getpgid(getppid()));
    exit(0);
}

However, handler function does not executed when I enter 'quit' while bc command is executed.

So, now, I don't know how to solve it. I really want to handle this problem. Please help me..

  • Related