Lately have been testing out using signals such as SIGINT and SIGHUP and their role on ongoing processes on Linux. Running the following code returned some interesting results.
#include <signal.h>
#include <stdio.h>
void routine(int p){
puts("Not finishing");
sleep(2);
}
main(){
int i = 0;
signal(SIGINT, routine);
signal(SIGHUP, routine);
while(1){
printf("%d \n", i++);
}
}
As you can see, it simply counts from 0 on an infinite loop. Then, by using kill -SIGINT on the process it created, I got the following:
Routine
As you can see, before the line I requested the routine to print, the program repeated the last number (and it does not happen always). I would really like to know why.
It is likely that you are narrowly avoiding horrible bugs by accident.
What I think is happening is that the signal sometimes interrupts while printf is in progress formatting the string into the output buffer. Then the puts in the signal handler inserts more string into the output buffer. Then the handler returns, printf inserts the newline and flushes the buffer.
But guess what would happen if this signal occurred just before the flush of a full 8K output buffer. The buffer positions would be at the end. Then the puts call happens, not realizing that printf is already in process of flushing and clearing the buffer. Where exactly would it be putting the puts string? At the beginning? At the end? Would the excess data printf was in the process of writing write over the string that puts had added? All of those things are possible.
Buffered C output is not reentrant and cannot be used in signal handlers.
Related
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void) {
for (int i = 1; i < 4; i++) {
printf("%d", i);
int id = fork();
if (id == 0) {
printf("Hello\n");
exit(0);
} else {
exit(0);
}
}
return 0;
}
For this code, it prints 11Hello on my computer. It seems counter-intuitive to me because "1" is printed twice but it's before the fork() is called.
The fork() system call forks a new process and executes the instruction that follows it in each process parallelly. After your child process prints the value of i to the stdout, it gets buffered which then prints the value of 'i' again because stdout was not flushed.
Use the fflush(stdout); so that 'i' gets printed only once per fork.
Alternately, you could also use printf("%d\n", i); where the new line character at the end does the job.
Where does the process start to execute after fork()
fork() duplicates the image of the process and it's context. It will run the next line of code pointed by the instruction pointer.
It seems counter-intuitive to me because "1" is printed twice but it's before the fork() is called.
Read printf anomaly after "fork()"
To begin with, the for loop is superfluous in your example.
Recall that the child copies the caller's memory(that of its parent) (code, globals, heap and stack), registers, and open files. To be performant or there may be some other reason, the printf call may not flush the buffer and put the things passed to that except for some cases such as appending new-line-terminator.
Before forking, the parent(main process) is on the way.
Let's assume we're on a single core system and the child first preempts the core.
1 is in the buffer because its parent put it into that before forking. Then, the child reaches second print statement, a caveat here is that the child can be orphaned at that time(no matter for this moment), passing "Hello\n" string including new-line character giving rise to dump the buffer/cache(whatever you call.) Since it sees \n character, it flushes the buffer including prior 1 added by its parent, that is 11Hello.
Let's assume the parent preempts the core at first,
It surrenders after calling exit statement, bringing on the child to be orphaned, causing memory leak. After that point, the boss(init possessing process id as 1) whose newly name I forget(it may be sys-something) should handle this case. However, nothing is changed as to the printing-steps. So you run into again 11Hello except if not the buffer is flushed automagically.
I don't have much working experience with them but university class(I failed at the course 4 times). However, I can advise you whenever possible use stderr while coping with these tings since it is not buffered, in lieu of stdout or there is some magical way(I forget it again, you call it at the beginning in main()) you can opt for to disable buffering for stdout as well.
To be more competent over these topics, you should glance at The Linux Programming Interface of Michael Kerrisk and the topics related to William Pursell,
Jonathan Leffler,
WhozCraig,
John Bollinger, and
Nominal Animal. I have learnt a plethora of information from them even if the information almost wholly is useless in Turkey borders.
*Magic means needing a lot of details to explain.
I'm writing a simple program in c, the program has two threads and two global's var, but the printf function not working, I know that printf is not thread safe and also if I will add \n in the print it will work, but I want to understand why it's not working without that?
I'm adding the code,
#include <pthread.h>
#include <stdio.h>
int i;
int j;
void* runi(void* _temp)
{
while(1)
{
i++;
if(i==1000)
{
printf("i: %d",i);
}
}
return NULL;
}
void* runj(void* _temp)
{
while(1)
{
j++;
if(j==1000)
{
printf("j: %d",j);
}
}
return NULL;
}
main ()
{
pthread_t threadI,threadJ;
pthread_create(&threadI,NULL,runi,NULL);
pthread_create(&threadJ,NULL,runj,NULL);
pthread_join(threadI,NULL);
pthread_join(threadJ,NULL);
return 0;
}
printf is somehow thread safe* (see discussion in unlocked_stdio(3)..., and consider flockfile(3)) but stdio is buffered, and you should call fflush(3) in your routines.
(printf is perhaps thread safe because two concurrent printf might not intermix their output, but nothing is told about flushing buffers)
So code instead
if(i==1000) {
printf("i: %d",i);
fflush(stdout);
}
(then you'll see some output)
BTW, I recommend ending most of your printf format control strings with a newline \n.... You could also add some delay by doing some nanosleep(2) or usleep(3) in your runi & runj routines.
It is the buffering which explains that you are disappointed. And stdout should be buffered for efficiency reasons (see setvbuf(3)...). Be aware that system calls (listed in syscalls(2) for Linux) such as write(2) are quite expensive operations. On Linux use strace(1) to understand what system calls are done.
If you want to understand the implementation of printf on Linux, study the source code of your C standard library - which is free software. It probably is GNU glibc, but could be something else like musl-libc, etc.
BTW, your threads are never ending (since runi and runj never return), and you pthread_join them. That call is blocking indefinitely. Use ltrace(1) to observe that.
You could also consider adding some sleep(2); fflush(stdout); in your main before the first pthread_join; you'll then observe some output.
At last, for such experiments, I recommend some periodic printing. Replace the i==1000 condition by i%10000 == 0 ....
You never explicitly flush your stdout so its gets flushed when its buffer (perhaps 8Kbytes) is full, or at end of your main (which is not reached in your case). Jonathan Leffler cleverly commented that you might need to wait an hour for that (buffer full condition) to happen.
Beware of race conditions and of undefined behavior.
I thought I was doing something simple here, but C decided to go asynchronous on me. I'm not sure what's going on. Here's my code:
#include <stdio.h>
int main() {
printf("start");
sleep(5);
printf("stop");
}
When I compile and run, I notice that sleep(5) works like a charm. But the compiler decided it was a good idea to skip the first printf() and go out of order, so when running, the program waits for 5 seconds and then prints startstop.
What's the deal? My theory is that the program initiates the print operation with the shell, then continues with the program, leaving Bash to wait until the program is no longer busy to actually render the strings. But I really don't know.
Thanks
printf uses buffered output. This means that data first accumulates in a memory buffer before it is flushed to the output source, which in this case is stdout (which generally defaults to console output). Use fflush after your first printf statement to force it to flush the buffered data to the output source.
#include <stdio.h>
int main() {
printf("start");
fflush(stdout);
sleep(5);
printf("stop");
}
Also see Why does printf not flush after the call unless a newline is in the format string?
Try adding '\n' to your printf statements, like so:
#include <stdio.h>
int main() {
printf("start\n");
sleep(5);
printf("stop\n");
}
The compiler is not executing this out of order. Just the output is getting accumulated, and then displayed when the program exits. The '\n' will invoke the line discipline in the tty drivers to flush the output.
Read this Q&A, it explains it.
When you create a thread does it automatically start the thread function that's in the parameter?
I'm using
iret1 = pthread_create(&client[i++].tID, NULL, thread_function, NULL);
printf("Thread Created"); //for testing purposes
In my thread function I have a print statement at the very top. ex:
void *thread_function(void *arg){
printf("Entered thread function");
...
}
Instead of printing Entered thread function it prints Thread Created right after
And it doesn't print Entered thread function until I start another thread, is there a reason for this?
You need at least to add a newline \n at the end of every printf(3) format function, and often to call fflush(3), e.g. add a call to fflush(NULL); after each of your two printf ...
Don't forget that <stdio.h> functions are buffered. See setvbuf(3) function and man page.
The reason why your output is not printed as soon as you want it to be is that it is staying in the buffer of stdout.
And you probably have no guarantee on the output. The individual characters might perhaps be intermixed. Read unlocked_stdio(3) and flockfile(3) for details.
You may want to read (several times) some pthread tutorial...
PS you could consider using directly the write(2) syscall (without using any <stdio.h> function).
I am a newbie in Linux programming.I copied the code below from a book:
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void ouch (int sig)
{
printf("OUCH! - I got signal %d\n", sig);
(void) signal(SIGINT, SIG_DFL);
}
int main ()
{
(void) signal(SIGINT, ouch);
while(1)
{
printf("Hello World!\n");
sleep(1);
}
}
It was expected to print something when Ctrl+C was entered.But it do nothing but print Hello World!.
EDIT:
I am so sorry that I have binded the Ctrl+C as a short-cut key for copy.
Sorry for trouble caused.
My Suggestion is don't use printf in siginal handler (ouch), it may be undefined behavior. Async-signal-safe functions: The list of safe functions that can be call in signal handler man page.
It is not safe to call all functions, such as printf, from within a signal handler.
A useful technique is to use a signal handler to set a flag and then check that flag
from the main program and print a message if required.
Reference: Beginning Linux Programming, 4th Edition,In this book exactly your code is explained, Chapter 11: Processes and Signals, page 484
An additional helpful link:
Explanation: Use reentrant functions for safer signal handling
Sorry, I can't see a question here... but I can guess what you are interested in.
printf() is a stateful function, thus not reentrant. It uses a FILE structure (variable name is 'stdin') to keep it's state. (It is like calling fprintf(stdin,format,...)).
That means, dependant on implementation and 'luck', calling printf() from a signal handler may print what you expect, but also may print nothing or may even crash or worse, smash your memory! Anything could happen.
So, just don't call functions from within a signal handler that are not explicitely marked 'signal-safe'. You will avoid lot's of headaches in the long term.
Put an fflush(stdout) in your signal handler. It was just buffered, then the second SIGINT exited the program before the buffer could be flushed.