Is this loop busy waiting, I would think the wait call takes care of that. If it is, how can it be fixed to not busy wait?
id = fork();
for (i = 0; i < 20; i++)
{
switch (id)
{
case 0:
/* do stuff with child */
exit(0);
default:
{
if (children>=3) {
int s;
wait(&s);
children--;
}
children++;
id = fork();
}
}
}
wait will cause the kernel to select other jobs that are not marked as blocked, so this isn't a case of busy-waiting. Also isn't switch a bit excessive for a fork(), why not use a simple if statement?
You are right, wait waits non-busy by handing over the CPU to the kernel until the child has exited.
It's not really buys waiting (it doesn't check the status of the children in a loop; instead if blocks inside the wait() call).
Nonetheless, the code can hog the CPU depending on what happens in do stuff with child. That will look like busy waiting (CPU usage 100%) even though it's really several processes doing actual work.
I agree with you, waiting on the death of a child (even inside a loop) would not be busy waiting. OTOH you can get in real trouble if one or more of the child processes are compute intensive. The compute-intensive children will always be ready to run and it is not guaranteed that the parent will get the CPU.
Related
I have a thread running in while with condition and it has sleep of 2 minutes.
(i.e.
while (condition) {
//do something
sleep(120);
}
)
To terminate the thread gracefully, I used pthread_join() and made while condition to false (e.g. someflag = 0)
And its working to terminate the thread, but if the thread is sleeping, it doesn't terminate until it finishes sleeping.
This is the problem I need avoid; I need to make thread come out early even if it is in sleep.
None of the above. Instead of while (condition) sleep(120); you should be using a condition variable:
while (condition) {
...
pthread_cond_timedwait(&condvar, &mutex, &abstime);
...
}
I chose pthread_cond_timedwait assuming you actually need to wake up and do something every 120 seconds even if nobody signals you, but if not you could just use pthread_cond_wait instead. The signaling thread needs to call pthread_cond_signal(&condvar) after changing the condition, and of course all access (reads and writes) to the state the condition depends on need to be protected by a mutex, mutex. You have to hold the mutex while calling pthread_cond_[timed]wait. If you have further questions on how to use condition variables, search the existing questions/answers (there are lots) or ask a follow-up.
This may not be the right answer, however I can suggest a work around to break sleep() of 120 sec into smaller time such as 2 seconds and put that in loop. Every time the loop executes, you can check for condition e.g.
while (condition)
{
//do something
int i = 0;
while(condition && (60 > i))
{
sleep (2);
i++;
}
}
I hope someone will surely paste better answer.
My problem is that I cannot reuse cancelled pthread. Sample code:
#include <pthread.h>
pthread_t alg;
pthread_t stop_alg;
int thread_available;
void *stopAlgorithm() {
while (1) {
sleep(6);
if (thread_available == 1) {
pthread_cancel(alg);
printf("Now it's dead!\n");
thread_available = 0;
}
}
}
void *algorithm() {
while (1) {
printf("I'm here\n");
}
}
int main() {
thread_available = 0;
pthread_create(&stop_alg, NULL, stopAlgorithm, 0);
while (1) {
sleep(1);
if (thread_available == 0) {
sleep(2);
printf("Starting algorithm\n");
pthread_create(&alg, NULL, algorithm, 0);
thread_available = 1;
}
}
}
This sample should create two threads - one will be created at the program beginning and will try to cancel second as soon it starts, second should be rerunned as soon at it was cancelled and say "I'm here". But when algorithm thread cancelled once it doesn't start once again, it says "Starting algorithm" and does nothing, no "I'm here" messages any more. Could you please tell me the way to start cancelled(immediately stopped) thread once again?
UPD: So, thanks to your help I understood what is the problem. When I rerun algorithm thread it throws error 11:"The system lacked the necessary resources to create another thread, or the system-imposed limit on the total number of threads in a process PTHREAD_THREADS_MAX would be exceeded.". Actually I have 5 threads, but only one is cancelled, others stop by pthread_exit. So after algorithm stopped and program went to standby mode I checked status of all threads with pthread_join - all thread show 0(cancelled shows PTHREAD_CANCELED), as far as I can understand this means, that all threads stopped successfully. But one more try to run algorithm throws error 11 again. So I've checked memory usage. In standby mode before algorithm - 10428, during the algorithm, when all threads used - 2026m, in standby mode after algorithm stopped - 2019m. So even if threads stopped they still use memory, pthread_detach didn't help with this. Are there any other ways to clean-up after threads?
Also, sometimes on pthread_cancel my program crashes with "libgcc_s.so.1 must be installed for pthread_cancel to work"
Several points:
First, this is not safe:
int thread_available;
void *stopAlgorithm() {
while (1) {
sleep(6);
if (thread_available == 1) {
pthread_cancel(alg);
printf("Now it's dead!\n");
thread_available = 0;
}
}
}
It's not safe for at least reasons. Firstly, you've not marked thread_available as volatile. This means that the compiler can optimise stopAlgorithm to read the variable once, and never reread it. Secondly, you haven't ensured access to it is atomic, or protected it by a mutex. Either declare it:
volatile sig_atomic_t thread_available;
(or similar), or better, protect it by a mutex.
But for the general case of triggering one thread from another, you are better using a condition variable (and a mutex), using pthread_condwait or pthread_condtimedwait in the listening thread, and pthread_condbroadcast in the triggering thread.
Next, what's the point of the stopAlgorithm thread? All it does is cancel the algorithm thread after an unpredictable amount of time between 0 and 6 seconds? Why not just sent the pthread_cancel from the main thread?
Next, do you care where your algorithm is when it is cancelled? If not, just pthread_cancel it. If so (and anyway, I think it's far nicer), regularly check a flag (either atomic and volatile as above, or protected by a mutex) and pthread_exit if it's set. If your algorithm does big chunks every second or so, then check it then. If it does lots of tiny things, check it (say) every 1,000 operations so taking the mutex doesn't introduce a performance penalty.
Lastly, if you cancel a thread (or if it pthread_exits), the way you start it again is simply to call pthread_create again. It's then a new thread running the same code.
if I have a program like this:
int i = 0;
int status;
bool result = true;
for(i = 0; i < numfiles; i++) { // LOOP 1
if (fork() == 0) {/* Child */
if (substLines(s1, s2, filenames[i])) {
exit(0);
} else {
exit(2);
}
}
}
for(i = 0; i < numfiles; i++) { // LOOP 2
wait(&status);
....
}
return result;
}
I have the following question.
what happens if a child process exists, before the program even knows about the wait(). I guess my question is regarding how a program is 'read'. Again, for example. If I exit from the first child, whilst still going through LOOP 1, what happens (does it even know about LOOP 2 at this point)?
is this a concurrent program? the parent seems to be waiting on the children after is forked them all, so i would say yes?
The man page of wait says
If a child has already changed state, then these calls return immediately. Otherwise they block until either a child changes state or a signal handler interrupts the call
so question1 doesn't matter
and question2, the answer is no.
Concurrency means they are running at the same time. It needs mutil-core CPU or more than one computer such as distributed system.
your program is multi-process, it is just Parallelism, which means they are running one by one under the schedule of CPU, for more info: Scheduling_(computing)
Just an addition to #simon_xia's excellent answer.
A killed or exited process becomes a zombie until its parent calls wait for it. And yes, this is the official terminology. :-) In zombie state everything is cleaned up (memory pages, open files, env, etc), just the exit status or killing signal number are kept.
Please consider this code in c:
int main()
{
pid_t cpid;
cpid = fork();
if (cpid == -1)
{
perror("fork");
return 0;
}
if (cpid == 0)
{
printf("I'm child\n");
_exit(0);
}
else
{
while(1)
{
printf("I'm parent\n");
sleep(1);
}
}
return 0;
}
After running the code, I expect it to run child and exits it once it's done.
But when I run
pgrep executable_name
or
ps fax
it shows the child process id and I don't know if its just a history crap of working process or it really does not end/terminate the child process?
thanks in advance
The child will remain until its parent dies or the parent cleans it up with the wait system calls. (In the time between the child terminating and it being cleaned up, it is referred to as a zombie process.)
The reason is that the parent might be interested in the child's return value or final output, so the process entry stays active until that information is queried.
edit:
Example code for using the sigchld handler to immediately clean up processes when they die without blocking:
http://arsdnet.net/child.c
Be mindful of the fact that system calls (like sleep, select, or file read/writes) can be interrupted by signals. This is a normal thing you should handle anyway in unix - they fail and set errno to EINTR. When this happens, you can just try again to finish the operation. This is why my example code calls sleep twice in the parent - the first long sleep is interrupted by the child dying, then the second, shorter sleep lets us confirm the process is actually cleaned up before the parent dies.
BTW signal handlers usually shouldn't do much, they should return as soon as possible and avoid things that aren't thread safe; printfing in them is usually discouraged. I did it here just so you can watch everything as it happens.
You need to call wait() in the parent, otherwise the child process will never be reaped (it becomes a zombie).*
* Unless the parent itself also exits.
Hey guys I seem to be lost. I am supposed to be able to increment a count in a child inside an infinite loop, and to have the count be printed every time the parent sends a signal, which should be every 1 second. I wrote my code but I thought that after using fork, the child and parent processes run at the same time, however this is not the case so I'm not sure how to tackle this problem. Any help would be great
What you are describing should work in theory.
Writing parallel code can be tricky, especially using fork(), if you're not familiar with the process.
Here is my suggestion: add a bunch of debug prints throughout your code, for example:
int pid = fork();
if(pid == -1) {
printf("Fork failed!\n");
} else if (pid) {
printf("I'm the parent!\n");
// Do stuff
printf("Parent exiting\n");
exit(0);
} else {
printf("I'm the child!\n");
// Do stuff
printf("Child exiting\n");
exit(0);
}
Then you can see if your program is behaving the way it should.
Also add a printf() statement to your signal handler so you can make sure it is being called.
The child process should be able to just run sleep(), and have the parent send SIGALRM to wake it up. Perhaps you made the child sit in a busy loop, consuming so much CPU that the parent didn't get to run as predicted.
Of course, answers to questions like these are way better if you show your code.