1

I've been studying this link to finish my shell assignment: http://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs and it's been particularly helpful. My confusion is that, to give the shell control of the stdin file descriptor again, I need to call tcsetpgrp from the shell after the child is terminated.

How do I get tcsetpgrp() to work in C?

I've searched different Stack Overflow questions, but none properly tell me why GNU promotes this approach. Because the shell currently is in the "background", tcsetpgrp() will send SIGTTOU to my process group. The current solution is to ignore it before calling the method and maybe reset it to default afterwards. What should I do?

EDIT: I would like to note that the child is first set in another process group before the shell passes control of stdin to it with tcsetpgrp(). Once the child dies, the shell calls tcsetpgrp() to reclaim stdin. GNU suggests this as a possible implementation, but says it uses a slightly different implementation for simplicity here.

If tcsetpgrp() is called by a member of a background process group in its session, and the calling process is not blocking or ignoring SIGTTOU, a SIGTTOU signal is sent to all members of this background process group.

Community
  • 1
  • 1
Daniel Handojo
  • 612
  • 5
  • 19
  • Does the information on POSIX's [general terminal interface](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap11.html#tag_11) help at all? You can also find the POSIX specifications of `tcsetpgrp()` and related functions there. – Jonathan Leffler Jan 24 '16 at 06:12
  • From what I can see, there's a paragraph in "Process Groups" that says if the foreground process group doesn't exist anymore, then the terminal has no foreground process. It doesn't specify what happens afterwards. It may be relevant to note, and I'll put it in the question, but each forked child from the shell is put into its own process group. – Daniel Handojo Jan 24 '16 at 06:28

1 Answers1

4

I'm also towards the end of implementing a shell program, and can take a stab at this question:

TL;DR: even though the shell will be a background process at that point, it needs to reclaim the terminal foreground for itself once the most recent foreground process group exits; otherwise the terminal will hang and no process will consume the user's input.

Here's what the session looks like when a shell launches a job from a line of command:

  1. before the child processes call execve(), they are assigned into a process group, so that it's simpler to manage them as a job;
  2. now that the shell and the child processes are in different process group, and that the terminal can only serve one process group at a time, the shell has to donate the terminal foreground to this child process group, so that the child job could read inputs and receive signals directly from the user;
  3. after the foreground donation, the shell becomes a background process, but since there's no point in running the shell in the background (its main function is to read/write to the terminal and launch jobs), it should not proceed until it reclaims the foreground;
  4. another reason why the shell must immediately reclaim the foreground after the exit of the most recent child foreground process group, is that there will be no running process consuming the terminal input/signal between the time a) when the child foreground process group exit, and b) when the shell reclaims the foreground. The terminal will essentially hang and become unresponsive;
  5. as for why the shell must reclaim the foreground itself, it's because the child processes will be calling execve() and loading entirely new process images. It is extremely difficult to enforce and advocate for a contract where every child process in the foreground returns the foreground back to the shell process;
  6. lastly, since tcsetpgrp() sends the caller background process a SIGTTOU, the shell must register an ignorer handler for SIGTTOU, at least during the time it's reclaiming the terminal foreground;

The GNU C Library manual also has another section (28.5.4 Foreground and Background) that briefly explains why the shell must reclaim the terminal forg

Haiyun_Xu
  • 41
  • 3