steps to terminate a shell - glibc

I've read the chapter about the job control in the glibc manual, but I'm wondering what to do with the remaining jobs when the shell is terminated.
I suppose the following steps (following the convention of posix to handle orphaned process groups the first two steps seems obvious):
send an HUP signal to the jobs with the shell's sid
send a CONTINUE signal to the stopped jobs with the shell's sid
free up the resource allocated for the job's data structures
My problem is what if the jobs survive?
I thought that a chance would be changing their session id to free up the sid and disassociate the process group from the terminal (not sure if that makes sense)
Should I do ioctl(STDIN_FILENO, TIOCSCTTY) to make the session processes lose the controlling terminal and send the signals?
What to do with the tty? Should I launch a login and set it as a new controlling terminal process group of the tty?
I'm still confused and a clue would be appreciated.

send an HUP signal to the jobs with the shell's sid
No need for that. The kernel will send a HUP signal itself when the shell (the session leader) terminates.
send a CONT signal to the stopped jobs with the shell's sid
No need for that. The kernel will send it for you, too ;-)
free up the resource allocated for the job's data structures
No need for that, either. All resources used by a process will be freed up by the kernel when the process terminates.
My problem is what if the jobs survive?
I guess you can SIGKILL them, if that's really a problem. In unix, they're supposed to survive, if they handle SIGHUP.
The "modern" systemd takes a different approach, completely against that spirit, but I would not enter into that ;-)
Notes:
In linux, it's the kill_orphaned_pgrp() from kernel/exit.c which is responsible for sending the HUP+CONT to all stopped jobs from the session, and tty_signal_session_leader() from drivers/tty/tty_jobctl.c, called via tty_vhangup_session() and __tty_hangup() which is resposible for sending the HUP to the processes from the foreground process group.

Should I launch a login and set it as a new controlling terminal process group of the tty?
I read up and I think the answer should be no.
For a character based terminal, the root process (initd/systemd/launchd etc) forks and execs getty for the preconfigured terminals or at a specific event.
Getty opens the terminal files for read/write and associates the std file descriptors to the terminal, sets a simple environment from a configuration file and prompts for a username, then execs login for that username.
Login changes the ownership and permission rights for the terminal, changes the persona of the process (effective and real uid, gid, supplement groups), and execs a login shell
When a shell terminates, its parent process get notified by a sigchd, and relaunches getty...
So the tty initialization/destruction is not a task for the shell..
Yet not sure on how to treat the survived process groups..

Related

How do you signal a process (PID) to restart in the same shell where it is running, from another shell using bash?

I have one terminal open with a java server running. I can easily get the process-ID (PID) of this JAR process. From another terminal, I want to signal this process to stop and restart in that same terminal where is is currently running. Is this possible using bash? Is there any signal i can send to the PID to make it stop and start again?
From another terminal, I want to signal this process to stop and restart in that same terminal where is is currently running. Is this possible using bash?
You can send signals to a process via the kill command. You may need to either be a privileged user or have the same UID as the process you're signaling.
But read on ...
Is there any signal i can send to the PID to make it stop and start again?
If you mean "stop" as in terminate and "[re]start" as in run from the beginning as if a new process, then there is no signal for which that is the default handling. A process could provide such behavior in response to a signal of its choice, but you cannot evoke it from an arbitrary process.
On the other hand, if you want to "stop" in the sense of temporarily suspending operations, and to "start" in the sense of resuming from such a stop, then there are SIGSTOP and SIGCONT, for which the default handling should suffice. Be aware, however, that stopping a process in this sense probably will not take it out of the foreground (if it is in the foreground), and that processes can block, ignore, or provide their own handling for those signals.
You can send signals with kill.
kill -s <SIGNAL> <PID>
will send the signal <SIGNAL> to the process with pid <PID>.
To stop and continue, you can use SIGSTOP and SIGCONT, which acts basically like hitting Ctrl-Z to pause a program on the terminal.

In Windows 7, how to send a Ctrl-C or Ctrl-Break to a separate process

Our group has long running processes which run daily. The processes are typically started at 9pm on any given day and run until 7pm the next day. Thus they typically run 22hrs/day. They are started by scheduled tasks on servers under a particular generic user ID, and they start and run regardless of whether or not that user ID is logged on. Thus, they are windowless console executables.
The tasks orchestrate computations running on a large server farm. Generally these controlling tasks run uninterrupted for the full 22hrs/day. However, we often have a need to stop and restart these processes. Because they control a multitude of tasks running on our server farm, it is important that they be shut down cleanly, so that they can stop and shut down all the server farm processes. Which brings me to our problem.
The controlling process has been programmed to respond to ctrl-C and ctrl-break signals. This works fine when the process is manually started in a console where we have access to the console and can "type" ctrl-c or ctrl-break in the console window. However, as mentioned, the processes typically run as windowless scheduled tasks. Hence we cannot "type" anything into a non-existent console window. Because they are console processes that execute without a logon process, the also must be able to execute in a completely windowless environment. So, how do we set up the process to listen for a shut-down signal?
While the process does indeed listen for a ctrl-C and ctrl-break signal, I can see no way to send that signal to a process. This seems to be a fundamental problem in Windows, or am I wrong? I am aware of SendSignal.exe, but so far have been unable to get it to work. It fails as follows:
>SendSignal 26320
Sending signal to process 26320...
CreateRemoteThread failed with 0x00000005.
StartRemoteThread failed with 0x00000005.
0x00000005 == Access is denied.
Trying "taskkill" without -F results in:
>taskkill /PID 24840
ERROR: The process with PID 24840 could not be terminated.
Reason: This process can only be terminated forcefully (with /F option).
All other "kill" functions kill the process immediately rather than sending a signal.
One possible solution would be a file-watch based solution: create a watch for some modification of a specific file. But this is a hack and we would prefer to do it with appropriate signaling. Has anyone solved this issue? It seems to be so very basic a functionality, and it is certainly trivial to do it in a Unix environment. Surely Microsoft has provided SOME mechanism to allow clean shut down of a windowless executable?
I am aware of the thread below, whose question is virtually identical (save for the specification of why the answer is necessary, i.e. why one needs to be able to do this for a windowless, console-less process), but there is no answer there excpet for "use SendSignal", which, as I said, does not work for us:
Can I send a ctrl-C (SIGINT) to an application on Windows?
There are other similar questions, but no answers as yet.
Any help appreciated.
[Upgrading #Anon's comment to an answer for visibility]
windows-kill worked perfectly and managed to resolve access denial issues faced with SendSignal. A privileged user would have to run it as well of course.
windows-kill also supports both ctrl-c and ctrl-break signals.

Is it possible to find out whether a process was started by a user or by another process via CreateProcess or ShellExecute?

I wanted to know if there was any way of checking if a particular process was started by the user by him/her double clicking, typing the required commands in cmd, via the address bar in explorer, etc. or by another program using CreateProcess() or ShellExecute().
I tried checking the parent process id of the created process but failed to see any consistency among the parent pids of the user initiated processes. I wanted to know if there was any other way or a fool proof way using the ppids.
First you have to determine what the "process started by user" means to you. From Windows' point of view all the processes are started by another processes, whether it was somehow triggered by user or not.
I can only think of getting processes belonging to currently logged on user otherwise i doubt that you can distinguish processes created on a system.

I can't run more than 100 processes

I have a massive number of shell commands being executed with root/admin priveleges through Authorization Services' "AuthorizationExecuteWithPrivileges" call. The issue is that after a while (10-15 seconds, maybe 100 shell commands) the program stops responding with this error in the debugger:
couldn't fork: errno 35
And then while the app is running, I cannot launch any more applications. I researched this issue and apparently it means that there are no more threads available for the system to use. However, I checked using Activity Monitor and my app is only using 4-5 threads.
To fix this problem, I think what I need to do is separate the shell commands into a separate thread (away from the main thread). I have never used threading before, and I'm unsure where to start (no comprehensive examples I could find)
Thanks
As Louis Gerbarg already pointed out, your question has nothing to do with threads. I've edited your title and tags accordingly.
I have a massive number of shell commands being executed with root/admin priveleges through Authorization Services' "AuthorizationExecuteWithPrivileges" call.
Don't do that. That function only exists so you can restore the root:admin ownership and the setuid mode bit to the tool that you want to run as root.
The idea is that you should factor out the code that should run as root into a completely separate program from the part that does not need to run as root, so that the part that needs root can have it (through the setuid bit) and the part that doesn't need root can go without it (through not having setuid).
A code example is in the Authorization Services Programming Guide.
The issue is that after a while (10-15 seconds, maybe 100 shell commands) the program stops responding with this error in the debugger:
couldn't fork: errno 35
Yeah. You can only run a couple hundred processes at a time. This is an OS-enforced limit.
It's a soft limit, which means you can raise it—but only up to the hard limit, which you cannot raise. See the output of limit and limit -h (in zsh; I don't know about other shells).
You need to wait for processes to finish before running more processes.
And then while the app is running, I cannot launch any more applications.
Because you are already running as many processes as you're allowed to. That x-hundred-process limit is per-user, not per-process.
I researched this issue and apparently it means that there are no more threads available for the system to use.
No, it does not.
The errno error codes are used for many things. EAGAIN (35, “resource temporarily unavailable”) may mean no more threads when set by a system call that starts a thread, but it does not mean that when set by another system call or function.
The error message you quoted explicitly says that it was set by fork, which is the system call to start a new process, not a new thread. In that context, EAGAIN means “you are already running as many processes as you can”. See the fork manpage.
However, I checked using Activity Monitor and my app is only using 4-5 threads.
See?
To fix this problem, I think what I need to do is separate the shell commands into a separate thread (away from the main thread).
Starting one process per thread will only help you run out of processes much faster.
I have never used threading before …
It sounds like you still haven't, since the function you're referring to starts a process, not a thread.
This is not about threads (at least not threads in your application). This is about system resources. Each of those forked processes is consuming at least 1 kernel thread (maybe more), some vnodes, and a number of other things. Eventually the system will not allow you to spawn more processes.
The first limits you hit are administrative limits. The system can support more, but it may causes degraded performance and other issues. You can usually raise these through various mecahanisms, like sysctls. In general doing that is a bad idea unless you have a particular (special) work load that you know will benefit from specific tweaks.
Chances are raising those limits will not fix your issues. While adjusting those limits may make you run a little longer, in order to actually fix it you need to figure out why the resources are not being returned to the system. Based on what you described above I would guess that your forked processes are never exiting.

Can I handle the killing of my windows process through the Task Manager?

I have a windows C++ application (app.exe). When the app is closed, I need to perform some cleanup tasks specific to my application. What happens when this process (app.exe) is killed through the Task Manager. Assuming that the application is still responsive, can I somehow handle this situation in my app.exe?
I am looking for something similar to how kill <pid> in Linux will send the SIGTERM signal to the process indicated by pid. I could then register my own signal handler for SIGTERM and perform the cleanup.
There are two ways to kill application in Task Manager.
Killing through Applications tab would roughly be equivalent of SIGTERM. Application may intercept it and do more processing, since it's basically sending a "close window" message. Message to catch is WM_CLOSE.
Killing through Processes tab would roughly be equivalent of SIGKILL. There is nothing you can do to intercept that, short of monitoring user's actions in Task Manager's listbox and End Process button, or having a watchdog process that will see when the first one is killed.
Alternatively, design the application in a way that does not require cleanup, or in a way that it will perform cleanup at startup.
I think you will need another PID that is monitoring the PID of your app.exe and does the necessary work at the time.
That depends, if the user chooses to "End Task" your application you will be notified and you can handle it see this.
but if the user chooses to end the process, you have no way to handle it in your application. the easiest way would be a second process or you can inject into process manager and hook the TerminateProcess API.

Resources