Linux schedule task when another is done - linux

I have a task/process currently running. I would like to schedule another task to start when the first one finished.
How can I do that in linux ?
(I can't stop the first one, and create a script to start one task after the other)

Somewhat meager spec, but something along the line of
watch -n 1 'pgrep task1 || task2'
might do the job.

You want wait.
Either the system call in section 2 of the manual, one of it's varients like waitpid or the shell builtin which is designed explicitly for this purpose.
The shell builtin is a little more natural because both processes are childred of the sell, so you write a script like:
#!/bin/sh
command1 arguments &
wait
command2 args
To use the system calls you will have to write a program that forks, launches the first command in the child then waits before execing the second program.
The manpage for wait (2) says:
wait() and waitpid()
The wait() system call suspends execution of the current process until one of its children terminates. The call wait(&status) is equivalent to:
waitpid(-1, &status, 0);
The waitpid() system call suspends execution of the current process until a child
specified by pid argument has changed state.

Related

fork/vfork, exec and waitpid in atomic way

Let suppose that process-A calls fork
pid = fork();
...
waitpid( pid, ...);
Is it possible, that between these calls (fork and waitpid) proccess-B, which is created by fork(), may to finish? Then some new process-C starts and gets a pid is equal to an old pid of process-B. And after that waitpid will waits the end of process-C, not B.
The exec-family calls don't return a value and a control if they are successful. The exec starts new process instead current process but keeps a process pid. Is it an any guaranteed way to do fork/vfork + exec + waitpid as a truly "atomic" operation and to get result of a process which is created by exec?
Does bash/shell run, wait commands and return their results in an "atomic" way?

In Linux, how can I wait until a process I didn't start finishes?

I have a monitoring program that I'd like to check on various processes in the system, and know when they terminate. I'd also like to know their exit code, in case they crash. However, my program is not a parent of the processes to be monitored.
In Windows, this is easy: OpenProcess for SYNCHRONIZE rights, WaitForMultipleObjectsEx to wait for any of them to terminate, then GetExitCodeProcess to find out why it terminated (with NTSTATUS error codes if the reason was an exception).
But in Linux, the equivalent of these, waitpid, only works on your own child processes, not unrelated processes. We tried ptrace, but this caused its own issues, such as greatly slowing down signal processing.
This program is intended to run as root.
Is there a way to implement this, other than just polling /proc/12345 until it disappears?
Can't think of an easy way to collect the termination statuses, but as for simple death events, you can, as root, inject an open call to a file you'll have the other end of and then you can do select on your end of the file descriptor.
When the other end dies, it'll generate a close event on the filedescriptor you have the other end of.
A (very ugly) example:
mkfifo /tmp/fifo #A channel to communicate death events
sleep 1000 & #Simulate your victim process
echo $! #Make note of the pid you want
#In another terminal
sudo gdb -ex "attach $thePid" -ex ' call open("/tmp/fifo",0,0)' -ex 'quit'
exec 3>/tmp/fifo
ruby -e 'fd = IO.select([IO.for_fd(3)]); puts "died" '
#In yet another terminal
kill $thePid #the previous terminal will print `died` immediately
#even though it's not the parent of $thePid

Fork()-ing a new process

Fork()-ing a process will end up calling do_fork() inside kernel, making an exact copy of itself. When I read through books, it says that child of fork will call exec to create the new process.
example:
ls command on a shell, will create this way.
sh(Parent)
|
sh(Child)
|
ls(New Process)
But, I am not able to understand how & where the exec*() is called?
Because, All I can see is the shell(child) is what created in fork.
But, when and where will the new process be created/executed?
You have to exec() if you actually want a new program running in one of the processes (usually the child but not absolutely necessary). In your specific case where the shell executes ls, the shell first forks, then the child process execs. But it's important to realise that this is two distinct operations.
All fork() does is give you two (nearly) identical processes and you can then use the return code from fork() to decide if you're the parent (you get the positive PID of the child, or -1 if the fork() failed) or child (you get 0).
See this answer for a description on how fork() and exec() work together (under your control) and how they can be used without each other.
Similar to do_fork(), the exec stuff all boils down to calls to do_execve, located in exec.c.

Perl: tail file in background while running another system command in loop

I'm trying to write a Perl script to capture system log output while a loop runs a system command at intervals. I want the script to do the equivalent of something I often do on the (unix) command line: taking Java process thread dumps by tailing /var/log/jbossas/default/console.log into a new file in the background, while running kill -QUIT [PID] an arbitrary number of times at intervals, in the foreground. I do not need to examine or process the log file output while it's being tailed, I just want it to go to a new file while my loop runs; once the loop exits, the background task should exit too.
# basic loop
# $process is PID given as argument
my $duration = 6;
my $dumps = 0;
until ($dumps == $duration) {
system "kill -QUIT $process";
$dumps++;
print STDOUT "$dumps of $duration thread dumps sent to log.\n";
print STDOUT "sleeping for $frequency seconds\n";
sleep 30;
}
Somehow I need to wrap this loop in another loop that will know when this one exits, and then exit the background log tailing task. I realize that this should be trivial in Perl, but I am not sure of how to proceed, and other questions or examples I've found are not doing quite what I'm trying to do here. Seems like using Perl's system blocks my proceeding into the inner loop; exec forks off the tail job so I'm not sure how I'd exit it after my inner loop runs. I'd strongly prefer to use only core Perl modules, and not File::Tail or any additional CPAN modules.
Thanks in advance for any feedback, and feel free to mock my Perlessness. I've looked for similar questions answered here, but if I've missed one that seems to address my problem, I'd appreciate your linking me to it.
This is probably best suited with an event loop. Read up on the answer to Making a Perl daemon that runs 24/7 and reads from named pipes, that'll give you an intro on reading a filehandle in an event loop. Just open a pipe to the tail output, print it off to the file, run the kill on a timer event, then once the timer events are done just signal an exit.

How can a process kill itself?

#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
int main(){
pid_t pid = fork();
if(pid==0){
system("watch ls");
}
else{
sleep(5);
killpg(getpid(),SIGTERM); //to kill the complete process tree.
}
return 0;
}
Terminal:
anirudh#anirudh-Aspire-5920:~/Desktop/testing$ gcc test.c
anirudh#anirudh-Aspire-5920:~/Desktop/testing$ ./a.out
Terminated
for the first 5 secs the output of the "watch ls" is shown and then it terminates because I send a SIGTERM.
Question: How can a process kills itself ? I have done kill(getpid(),SIGTERM);
My hypothesis:
so during the kill() call the process switches to kernel mode. The kill call sends the SIGTERM to the process and copies it in the process's process table. when the process comes back to user mode it sees the signal in its table and it terminates itself (HOW ? I REALLY DO NOT KNOW )
(I think I am going wrong (may be a blunder) somewhere in my hypothesis ... so Please enlighten me)
This code is actually a stub which I am using to test my other modules of the Project.
Its doing the job for me and I am happy with it but there lies a question in my mind how actually a process kills itself. I want to know the step by step hypothesis.
Thanks in advance
Anirudh Tomer
Your process dies because you are using killpg(), that sends a signal to a process group, not to a process.
When you fork(), the children inherits from the father, among the other things, the process group. From man fork:
* The child's parent process ID is the same as the parent's process ID.
So you kill the parent along with the child.
If you do a simple kill(getpid(), SIGTERM) then the father will kill the child (that is watching ls) and then will peacefully exit.
so during the kill() call the process switches to kernel mode. The kill call sends the SIGTERM to the process and copies it in the process's process table. when the process comes back to user mode it sees the signal in its table and it terminates itself (HOW ? I REALLY DO NOT KNOW )
In Linux, when returning from the kernel mode to the user-space mode the kernel checks if there are any pending signals that can be delivered. If there are some it delivers the signals just before returning to the user-space mode. It can also deliver signals at other times, for example, if a process was blocked on select() and then killed, or when a thread accesses an unmapped memory location.
I think it when it sees the SIGTERM signal in its process tables it first kills its child processes( complete tree since I have called killpg() ) and then it calls exit().
I am still looking for a better answer to this question.
kill(getpid(), SIGKILL); // itself I think
I tested it after a fork with case 0: and it quit regular from separate parent process.
I don't know if this is a standard certification method ....
(I can see from my psensor tool that CPU usage return in 34% like a normal program code with
a counter stopped ) .
This is super-easy in Perl:
{
local $SIG{TERM} = "IGNORE";
kill TERM => -$$;
}
Conversion into C is left as an exercise for the reader.

Resources