Kill all the process from main after specific time - c

Below is my query. I am having problem with the bold text.
"You will write a program that uses multiple processes to compute the sum of a set of (small) positive integers.
There are two types of processes for this homework:
I). A set of "slaves" processes: Each slave process gets two small integers from its argv, computes its sum and returns the result using the exit system call. So, a slave process is created for every sum.
II) A "master" process: This process is responsible for creating the slave processes, and coordinating the computation. Note that all the computation is done by the "slave" processes. All the numbers are provided in the command line argv. The master process also set a timer at the start of computation to 3 seconds. If the computation has not been finished by this time, the master process kills all the slaves and then exits. You should print an appropriate message(s) in this case. Note that the master process may have to create multiple sets of slave processes. For example, if there are 8 numbers to be added, then the master process will first create 4 slaves and get the result from them. At this point there are 4 numbers, and it creates 2.
slaves. Finally one slave is created to compute the overall sum. To make it simpler, if the number of integers to add is odd, the master adds a 0 to the list of numbers. This may happen at any step during the computation. The code for master process should be compiled separately and its executable code should be called master. The executable code for the slave process should be called slave. So, to compute the sum of the numbers 1 through 7, the command line will look like
master 1 2 3 4 5 6 7
Since the results are passed around by exit system call, keep the numbers small (single digit). Each slave process prints its process id, its operands, and their sum. Each time the master gets a result from a slave, it prints the pid of the slave and the partial sum."

You are asked to use processes. It means you need to fork for every worker that is needed. Also
The master process also set a timer at the start of computation to 3 seconds. If the computation has not been finished by this time, the master process kills all the slaves and then exits.
It would be best to set alarm, which would send you a signal SIGALARM and when it's received you will use kill on specific processes ids (you can get them from fork). If your workers will finish, so will your main process and alarm won't trigger.
It's somehow complicated task if you are new to multiprocess programming. Now just try creating some processes and killing them after for e.g. 3 seconds. If you will have more problems, post your code and ask specific questions.

When creating threads, store their identifiers.
After creating threads in main(), pause using e.g. sleep(3) or whatever.
Loop over the stored thread ID:s, calling pthread_cancel() to kill them. Killing threads that have already terminated will cause this call to fail, but that's fine.

not sure if i get your question right. You may want to start a helper thread for each worker thread that does the computing. Pass the tid of the worker thread to its helper thread and let the helper thread sleep for 3 seconds and then check if the worker thread has exited and if not just kills it.
Or alternatively if you have a dedicated timer module/task, you could start a timer for each worker thread.

Related

How to read the PID of the previous executed process in C?

I would like to read the PID of the previous executed process in C.
For example, I have process 1 which sleeps for 1s and when wakes up reads the PID of the process executing before the context switch. Process 1 runs with higher priority than the other processes so as when the sleep time finishes it immediately scheduled to run.
How can I get the information on which process PID run before its execution was interrupted so as process 1 executes?
I would like to read the PID of the previous executed process in C.
How can one determine which process was executed before or after, more on in a multiprocessor architecture in which several threads (even in the same process) can be executing fork() at the same time?
For example, I have process 1 which sleeps for 1s and when wakes up reads the PID of the process executing before the context switch.
how can it get the pid of the process that was executing before that context switch? In a context switch the process deciding the next process to execute doesn't tell the next process to execute which was the last. Even when a context switch happens by means of a hardware interrupt in which the process is not making a sleep()/wait()/pause() system call. System calls return information on how the system call went, but there's no place to store what process lead to a context switch and provide the number of the process id (indeed, it should be the thread id, as a process can have several threads and not only one)
Process 1 runs with higher priority than the other processes so as when the sleep time finishes it immediately scheduled to run.
Why do you assume process 1 runs at higher priority if the scheduler assigns priorities dynamically when considering which process to run next?
How can I get the information on which process PID run before its execution was interrupted so as process 1 executes?
You cannot. It's impossible as the context switch can happen because a hardware interrupt, when your process is not capable of storing it anywhere. Even signal handlers run in user mode, so there's no way in which you can have access to the last executed process. More because in a multiprocessor computer the kernel can be handling several context switches at the same time.
Indeed, telling a user process the pid of the process that was run last, could represent a security breach, as not all the processes belong to the same user. Remember today systems are not only multithread/multiprocess/multiprocessor, but also multiuser.

Time the duration of a program called by execv

I am making a C program that uses fork and execv to run other programs in parallel.
I can't seem to be able to time the duration of the execution of the program called by execv since the new process dies immediately after that program is done running. Another complication is not being able to use the parent process to wait for the child process to finish (I am using waitpid) because I need the parent process to do some other work instead of waiting for the child process to be finished.
So my question is: is there a way to measure the duration of the execv call without the use of an auxiliary fork, pthread or text file?
Thank you in advance
Your parent process knows when it issued the fork() system call. That's not exactly the moment that the execv'd process starts running, since the execv() system call takes some amount of time, but it's not totally unreasonable to include that time in the tally. If you accept that limitation, you can just record the start time as the time at which you called fork().
When the child terminates, the parent will receive a SIGCHLD signal. The default action for SIGCHLD is to ignore it, but you probably want to change that anyway. If you attach a signal handler to SIGCHLD, then in that signal handler you can call waitpid (with the WNOHANG option) until you've received all the child terminated notifications. For each notification, you record the notification time as the process's end time. (Again, if the system is under heavy load, the signal might lag from the termination, causing your time measure to be inaccurate. But most of the time, it will be accurate.)
Clearly, the parent needs to track more than one child process. So you'll need to use the child's PID to index these values.
Now you have a start time and an end time for each child process.
There's a small problem, though. You cannot attach the start time to the child process's PID until the fork() call returns to the parent. But it's entirely possible that the fork() call will return to the child, and that the child will call execv() and that the execv()'d process terminates all before the fork() call returned to the parent. (Honest. It happens.)
So it is possible for the SIGCHLD handler to receive a notification of the termination of a process whose start time has not yet been recorded.
This is easy to fix, but when you do so you need to take into account the fact that signal handlers cannot allocate memory. So if you're recording the start and end time information in dynamically allocated storage, you need to have allocated storage before the signal handler runs.
So the code will look something like this:
1. Allocate storage for a new process times table entry
(PID / start time / end time / status result). Set all
fields to 0 to indicate that the entry is available.
2. Recall the current time as start_time (a local variable,
not the table entry).
3. Fork()
4. (Still in the parent). Using an atomic compare-and-swap
(or equivalent), set the PID of the table entry created
in step 1 to the child's PID. If the entry was 0 (and is
now the PID) or if the entry was already the PID, then
continue to step 6.
5. If the entry has some other non-zero PID, find an empty entry
in the table and return to step 4.
6. Now record the start time in the table entry. If the table entry
already has an end time recorded, then the signal handler already
ran and you know how long it took and what its return status is.
(This is the case where the child terminated before you got to
step 4.) You can now report this information.
In the SIGCHLD signal handler, you need to do something like this:
For each successful call to waitpid():
1. Find the entry in the child process information table whose PID
corresponds to the PID returned by waitpid(). If you find one,
skip to step 4.
2. Find an empty entry in the child process information table.
Note that the signal handler cannot be interrupted by the main
program, so locking is not required here.
3. Claim that entry by setting its PID field to the PID returned by
waitpid() above.
4. Now that you have an entry, record the end time and return status
information in the table entry. If the table entry existed
previously, you need to put the entry on a notification queue
so that the main process can notify the user. (You cannot call
printf in a signal handler either.) If the table entry didn't
exist before, then the main process will notice by itself.
You might have to draw some diagrams to convince yourself that the above algorithm is correct and has no race conditions. Good luck.
Also, if you haven't done any of these things before, you'll want to do some reading :-)
waitpid(). Pay particular attention to the macros used to extract status information.
sigaction(). How to assign a handler function to a signal. If that's still greek to you, start with signal(7) or a relevant chapter in your Unix programming textbook.
Race conditions (from Wikipedia)
Compare and Swap (on Wikipedia). (Don't use their sample code; it doesn't work. GCC has a built-in extension which implements atomic compare and swap on any architecture which has a way of supporting it. I know that section is marked legacy and you should use the more complicated functions in the next section __atomic, but in this case the defaults are fine. But if you use __atomic_compare_exchange_n, kudos.)

More than just data communication between threads

Say I have 3 threads.
1st Thread is the controller where I create threads
2nd and 3rd is where the data processing is done
The catch is, the 2nd thread does a different operation than the 3rd. So I need a way to differentiate between the two different logic. Would just creating threads with different methods suffice?
No! That's because should thread 2 die, become unresponsive I need the 3rd to take it's place and start doing the job that the 2nd thread was doing, and create a new one to act as the 3rd but creating a new one to act as the 3rd is not my issue.
It's as I said, how to suddenly make the 3rd thread start doing the 2nd one's logic without starting a whole new thread for the previous 2nd thread and resetting it's variables
E.g. Thread 2 dies, Thread 3 now needs to start doing Thread 2's job and I need to create a new Thread to cover for Thread 3.
Note: Bonus question is how I can do it without losing the Thread 2 so that in the eventuality that it stops being unresponsive I can still re-use it?
Any help appreciated!
You picked the wrong tool for the job. If you need to handle a task dying or becoming unresponsive, you must isolate them with processes, not threads.
Threads share an execution environment. So if a thread corrupts or damages that execution environment, it can affect all the other threads. For example, say your thread dies in the process of adjusting shared structures. If you keep the lock on those shared structures, no other thread can ever access them. If you release the lock, other threads may access them and find them in a corrupted state.
Use multiple processes for this kind of isolation.

Using one process to signal multiple other processes "simultaneously"

I have two different applications that have to work together. process 1 acts as a time source and process 2 performs acts according to the time source provided by process 1. I need to run multiple copies of process 2. The goal is to have one time source process signaling 5-10 other processes at the same time, so they they all perform their work simultaneously.
Currently, I have this implemented in the following way:
The time source program starts, created a shared memory segment, creates an empty list of PIDs, then unlocks the segment.
Each time one of the client programs start, they go the shared memory, add their own pid to the list, and then unlock it.
The time source has a timer than goes off every 10ms. Every time the timer goes off, he cycles through the pid list, and sends a signal to everyone in it back to back.
This approach mostly works well, but I am hoping that it can be improved. I currently have two sticking points:
Very rarely, the signal delivered to one of the client processes will be skewed by ~2 milliseconds or so. The end result is: | 12ms | 8ms | instead of | 10ms | 10ms |.
The second issue is that all of the client programs are actually multithreaded and doing a lot of work (though only the original thread is responsible for handling the signal). If I have multiple client processes running at once, the delivery of the signals gets more sporatic and skewed, as if they are more difficult to deliver when the system is more taxed (even if the client process is ready and waiting for the interrupt).
What other approaches should I consider for doing this type of thing? I have considered the following (all in the shared memory segment):
Using volatile uin8_t flags (set by time source process, cleared by client).
Using semaphores, but if the time source process is running, and the client hasn't started yet, how do I keep from incrementing the semaphore over and over?
Condition variables, though there doesn't seem to be a solution that can be used in shared memory between unrelated processes.
Even if a process is in waiting state, ready to receive a signal, does not mean that the kernel is going to schedule the task yet, and especially when there are most tasks in running states than there are available CPU cores.
Adjusting the priority (or nice level) or processes and threads, will influence the kernel scheduler.
¨
You can also play around with the different schedulers that are available in your kernel, and their parameters.

One thread controlling many others

I have an application that waits for clients to connect. Each time a client connects, a new frame gets created (with the new socket file descriptor). I know how many clients will connect, after I reach that number I just run pthread_join in a for loop.
My problem is that I would like the main thread to control all the other threads. My goal is to have each thread send the same message back to the client, at the same time, and only once. There are multiple messages a thread can send.
My current thinking is to define a list of command, as follows:
char *commands[] = {
(char*) "TERMINATE\0",
.... };
And then specify a command number that represents which command to use in that char* array. All threads will do something like
write(sockfd, buffer[commandNumber], length[commandNumber]);
I thought about waiting on a condition variable, but I see two problems:
1) I want to make sure that each thread, although synchronized, execute the command only once.
2) The main thread that initiates the command has to know when all those threads is done executing the command.
Only way I see to execute 2) is to keep track of a counter (with mutexes), and when each thread executes the command, it can increase that counter. I am not sure I will be able to avoid a thread from running the command twice.
What is the best possible way please to coordinate multiple threads to execute a single action at once; and also be able to know when that action has finished executing for every thread please?
You might use a barrier to gate the operation.
Synchronizing the send
The main thread initializes a barrier named "Ready" to N+1. Then it begins accept()ing N client connections, spawning a worker thread for each. The new worker threads immediately wait on barrier "Ready".
After spawning the Nth (and last) worker, the main thread sets the desired command (perhaps using a global commandNumber). Then the main thread waits on barrier "Ready". As soon as all workers and the main thread have arrived (reaching the barrier's limit of N+1), all threads are released, knowing that they are ready to issue their command immediately.
(A common alternate approach is to use a predicate and condition variable rather than a barrier. For example, the main thread might spawn the Nth worker and then cond_broadcast() that it has set a flag ready = 1. This approach is flawed. The main thread cannot know that the Nth worker — or, indeed, any of the workers — are yet waiting on that condition. The barrier solves this problem.)
Indicating completion
Another N+1 barrier, "AllDone", could be used to indicate that the workers are all done. A semaphore initialized to -N and posted by workers would do the same. Having the workers close() their connections and the main thread select()ing or poll()ing connections would convey the same information, too.

Resources