How to clear the contents of scanf of a stopped process? - c

I am using fork and the child process reads data ten times from user using a scanf inside the for loop. The parent process however sends the SIGSTOP signal to child after 4 seconds of sleep and reads a value from the user and prints it. But if the user has entered data but not pressed enter for the scanf in the child process the parent process reads but prints the data written in the child process. How do I stop this from happeneing.
ch=fork();
if(ch==0)
{
for(i=0;i<10;i++)
{
fflush(stdin);
scanf("%s",buf);
printf("%d: %s\n",i,buf);
}
}
else
{
char buf2[100],cha;
sleep(4);
kill(ch,SIGSTOP);
write(STDOUT_FILENO,"\nchld stopped\n",14);
memset(stdin,0,sizeof(stdin));
read(STDIN_FILENO,buf2,2);
write(STDOUT_FILENO,buf2,2);
kill(ch,SIGCONT);
wait(SIGCHLD);
}
So the output for example comes like this:
a
0: a
b
1: b
ac (I dont press enter here and wait for SIGSTOP)
chld stopped
tr (Entered data for parent and pressed enter)
ac2: tr
c
3: c
... and so on
So after entering tr why does my parent display ac?

fflush(stdin) is never the right thing to do, although lots of people have tried it. fflush is only for output. Your memset is pure insanity. The argument to wait isn't supposed a signal number - it's not even the right type, so you should have got a warning which you apparently ignored.
Those are the easy errors. There is a deeper conceptual problems with what you're trying to do.
Since you didn't modify any tty settings, the tty is in canonical mode while your program is running. That means the tty handles line editing (backspace, Ctrl-U, Ctrl-W, etc.) and doesn't send anything to the program until the line is terminated.
When you have typed a partial line, that partial line is not in the stdin buffer. It's in the tty buffer. It doesn't belong to any process yet. That's why your parent process can read a line that was partially typed while the child was attempting to read. The child never got any of it.
To empty the tty buffer, this should work: turn off canonical mode; set non-blocking mode; read into a until an error occurs (EAGAIN/EWOULDBLOCK will happen in non-blocking mode when the tty has nothing left to give you); turn blocking and canonical mode back on. The idea is to consume whatever is currently available without waiting for more. Code to perform the individual steps should be easy to find.
In general, I question the wisdom of an interface that offers the user an opportunity to enter information, then spontaneously interrupts the reading of that information to read something else. It's going to cause users to shout at the secondary input prompt: HEY! I'M TYPING HERE!

Okay I found the solution.
I used tcflush(): flush non-transmitted output data, non-read input data, or both.
tcflush(STDIN_FILENO,TCIFLUSH); line just before the read in the parent did it.
I found the solution here...
How can I flush unread data from a tty input queue on a UNIX system?

It is because of read(), write() function. When you input something without pressing enter. It will be in stdinput, whatever in stdinput, it will read by read() function store in buf2 as specified in your example. And whatever in buf2, it will send to stdoutput by write(). You can see the difference when you comment read(), write() function, or just print "buf2".

Related

how to get a character from user without stopping the the execution in C language?

getch or getche stops the output until a character is not entered. I want my code to keep asking for character in a loop and not wants to stop the execution of code?
What you are looking for is a non-blocking input call (that means it does not block but return immediately if no input is available).
If you are talking about getch(), the curses function, it's easy to make it non-blocking: just call timeout(0).
Just for fun, I created a "snake" using curses functions stripped down to the bare minimum, for reference
The problem with your computer freezing and waiting for input when your CLI C or C++ program attempts to read a key from the keyboard (say, by using "getchar") is not under direct control of your program. What's happening "under the hood" is this: your program makes a function call to whatever "terminal" program is handling your from-keyboard input and to-screen output. In Linux this is called "console". In raw Windows it's called "cmd.exe". In Cygwin it's called "mintty.exe". It's the terminal which causes the "freeze" by failing to return until a user presses one-or-more keys followed by the Enter key.
To fix this, you need to temporarily change the settings of your terminal. To do that, research the name of the program used to configure your terminal. In Linux and Cygwin, this is "stty". The stty command for changing "timeout" from "∞ deciseconds" (the default) to "1 decisecond" (which is what you need) is "time 1".
A function for getting a keystroke without delaying program execution on a Linux or Cygwin system looks like this (you'll have to change the contents of the system() calls if your system uses something other than stty to configure its terminal):
// Check for recent keypress on keyboard; if there is one,
// get that character; but time-out after 1 decisecond if
// input does not immediately occur (keep executing program):
char getkey_unlocked (void)
{
char A;
system("stty -icanon");
system("stty -echo");
system("stty time 1"); // CHANGE TIMEOUT FROM ∞ TO 1/10 SECOND
A = (char)getchar();
system("stty echo");
system("stty icanon");
return A;
}
That will return "-1" if no key has been pressed, or the ASCII code for any key which is pressed.
You should use concurrent programming, with that you can do something like: while a father process waits the input, the child executes the rest of the code.
You can do that in linux by using the function fork().
To check if the current process is father or child you should do:
// CREATE PID AND PROCESS
pid_t pid;
pid = fork();
if (pid < 0)
puts("ERROR");
else if (pid == 0)
puts("CHILD");
// CODE YOU WANT TO EXECUTE
else
puts("FATHER");
// CODE THAT WAITS FOR INPUT
You can use threads too.

How fork() and scanf() work together?

I tried to see what happens if I read something from keyboard while I have multiple processes with fork() (in my case there are two children and a parent) and I discovered the following problem: I need to tell the parent to wait for children's processes, otherwise the program behaves strangely.
I did a research and I found that the problem is with the parent, he needs to wait for the child's process to end because if the parent's process ends first somehow he closes the STDIN, am I right? But also I found that every process has a copy of STDIN so my question is:
Why it works this way and why only the parent has the problem with STDIN and the children not, I mean why if the child's process ends first doesn't affect STDIN but if the parent's process ends first it does affect STDIN?
Here are my tests:
I ran the program without wait() and after I typed a number the program stopped, but then I pressed enter two more times and the other two messages from printf() appeared.
When I ran the program with wait() everything worked fine, every process called scanf() separately and read a different number.
Well, a lot of stuff is going on here. I will try to explain it step by step.
When you start your terminal, the terminal creates a special file having path /dev/pts/<some number>. Then it starts your shell (which is bash in this case) and links the STDIN, STDOUT and STDERR of the bash process to this special file. This file is called a special file because it doesn't actually exist on your hard disk. Instead, whatever you write to this file, it goes directly to the terminal and the terminal renders it on the screen. (Similarly, whenever you try to read from this file, the read blocks until someone types something at the terminal).
Now when you launch your program by typing ./main, bash calls the fork function in order create a new process. The child process execs your executable file, while the parent process waits for the child to terminate. Your program then calls fork twice and we have three processes trying to read their STDINs, ie the same file /dev/pts/something. (Remember that calling fork and exec duplicates and preserves the file descriptors respectively).
The three processes are in race condition. When you enter something at the terminal, one of the three processes will receive it (99 out of 100 times it would be the parent process since the children have to do more work before reaching scanf statement).
So, parent process prints the number and exits first. The bash process that was waiting for the parent to finish, resumes and puts the STDIN into a so called "non-canonical" mode, and calls read in order to read the next command. Now again, three processes (Child1, Child2 and bash) are trying to read STDIN.
Since the children are trying to read STDIN for a longer time, the next time you enter something it will be received by one of the children, rather than bash. So you think of typing, say, 23. But oops! Just after you press the 2 key, you get Your number is: 2. You didn't even press the Enter key! That happened because of this so called "non-canonical" mode. I won't be going into what and why is that. But for now, to make things easier, use can run your program on sh instead of bash, since sh doesn't put STDIN into non-canonical mode. That will make the picture clear.
TL;DR
No, parent process closing its STDIN doesn't mean that its children or other process won't be able to use it.
The strange behavior you are seeing is because when the parent exits, bash puts the pty (pseudo terminal) into non-canonical mode. If you use sh instead, you won't see that behavior. Read up on pseudo terminals, and line discipline if you want to have a clear understading.
The shell process will resume as soon as the parent exits.
If you use wait to ensure that parents exits last, you won't have any problem, since the shell won't be able to run along with your program.
Normally, bash makes sure that no two foreground processes read from STDIN simultaneously, so you don't see this strange behavior. It does this by either piping STDOUT of one program to another, or by making one process a background process.
Trivia: When a background process tries to read from its STDIN, it is sent a signal SIGTTIN, which stops the process. Though, that's not really relevant to this scenario.
There are several issues that can happen when multiple processes try to do I/O to the same TTY. Without code, we can't tell which may be happening.
Trying to do I/O from a background process group may deliver a signal: SIGTTIN for input (usually enabled), or SIGTTOU for output (usually disabled)
Buffering: if you do any I/O before the fork, any data that has been buffered will be there for both processes. Under some conditions, using fflush may help, but it's better to avoid buffering entirely. Remember that, unlike output buffering, it is impossible to buffer input on a line-by-line basis (although you can only buffer what is available, so it may appear to be line-buffered at first).
Race conditions: if more than one process is trying to read the same pipe-like file, it is undefined which one will "win" and actually get the input each time it is available.

How does scanf determine whether to block?

When I redirect a file to stdin using MyProgram < cl.txt command from the command line, scanfs doesn't wait me to press Enter.
But when I use scanf in my program without doing so, it does block until enter key is pressed.
How exactly does it determine that? Does it keep reading the stream until \n is encountered? or does it really wait me to press a key?
When I don't write anything and press Enter it doesn't stop blocking either and keeps asking. I'm really confused.
Does it keep reading the stream until '\n' is encountered?
Normally stdin is in line buffering mode (_IOLBF, see setvbuf). Whenever the buffer is empty, stdin waits for a whole new line to be entered, i.e. waits until you press Enter and \n is inserted into the buffer:
On Input, the buffer is filled up to the next newline character when an input operation is requested and the buffer is empty.
Note: the console (terminal) is most often implementing a buffering on its own, and does not send any data to the stream until you press Enter - this allows you to edit the data (like use delete, and backspace keys) before you send them to the application. Therefore even with no buffering on the stdin side (like when you perform setvbuf(stdin, NULL, _IONBF, 0)), the scanf may still wait until the Enter is pressed.
scanf is just reading from its input stream. If the input stream is a pipe, and the other end of that pipe is associated with a tty (which is usually the case if you are interactively entering data by pressing keys on a keyboard), scanf will return as soon as it reads data that completes its format string (or fails to match it). The tty, however, if it is in cooked mode (which is the default, and unless you make some effort to put the tty into raw mode, you should assume it is cooking what you type), will not write any data into the pipe until you hit return.
In other words, it's not your scanf that is blocking. (Well, it is blocking, but it's not the source of the experienced delay.) Rather, the tty driver is waiting for you to hit return before it passes any data to your program.
When you call scanf it immediately waits for input. in your first example, input is provided in the form of "cl.txt". In your second example, no input is provided until you press a key. Synchronous IO will block on its executing thread until it receives input.

I want to make a REPL-style program with pipes and signals, but my program locks

The program should fork, then the parent should read user input, send it to the child; the child should deal with it, then send a result to the parent, who prints it (it is required to work this way).
I've done a part of it, but the program locks after reading from the fifo the first time.
I suspect the problem is somewhere between lines 122–199. Making the pipe nonblocking makes the program jump through the scanf at 185 and loop indefinitely. Closing and reopening the pipe before writing and after reading leads to the same effect.
Here is the source: link.
Later edit (clarification):
The parent blocks before the printf at 184, when it reads the second command (the first time it seems to work just fine).
I haven't implemented the "child sends stuff back to the parent" part. At the moment I just want to make the child output the data it recieves through the pipe from the parent and then give control back to the parent to read another command.
The child lives in a paused state (pause()) while the parent reads input and sends it through the pipe, then it wakes up the child and goes in a paused state itself. The child reads data from the pipe and outputs it, then wakes up the parent and goes to sleep.
Did you use some multiplexing system call like select or poll which are able to test of a set of file descriptors has some of them ready (for input, or for output)?
Learn more about poll or about select and friends.
You should clarify your question which with part (parent or child) it is that locks.
Make sure all output is line feed terminated. It seems (from a quick reading) that you use puts(), which should take care of that.
Try calling fflush() on the output after the client is done, to make sure the output gets written to the pipe, if the child lives on while the parent reads its output. I didn't read your code closely enough to track down the lifetime handling.

Find out if pipe's read end is currently blocking

I'm trying to find out if a child process is waiting for user input (without parsing its output). Is it possible, in C on Unix, to determine if a pipe's read end currently has a read() call blocking?
The thing is, I have no control over the programs exec'd in the child processes. They print all kinds of verbose garbage which I would usually want to redirect to /dev/null. Occasionally though one will prompt the user for something. (With the prompt having no reliable format.) So my idea was:
In a loop:
Drain child's stdout, append it to a temporary buffer.
Check (no idea how) if the child is asking for user input, in which case the buffer is printed to stdout.
When the child exits, throw away the buffer.
The thing is, I have no control over the programs exec'd in the child processes. They print all kinds of verbose garbage which I would usually want to redirect to /dev/null. Occasionally though one will prompt the user for something. (With the prompt having no reliable format.) So my idea was:
In a loop:
Drain child's stdout, append it to a temporary buffer.
Check (no idea how) if the child is asking for user input, in which case the buffer is printed to stdout.
When the child exits, throw away the buffer.
You have these options:
if you know that the child will need certain input (such as shell that will read a command), just write to a pipe
if you assume the child won't read anything usually, but may do it sometimes, you probably need something like job control in the shell (use a terminal for communication with the child, use process groups and TIOCSPGRP ioctl on the terminal to get the child to the background; the child will get SIGTTIN when it tries to read from the terminal, and you can wait() for that). This is how bash handles things like "(sleep 10; read a;)&"
if you don't know what to write, or you have more possibilities, you will have to parse the output
That sounds as if you were trying to supervise dpkg where occasionally some post-inst script queries the admin whether it may override some config file.
Anyway, you may want to look at how strace works:
strace -f -etrace=read your.program
Of course you need to keep track of which fds are the pipes you write about, but you probably need only stdin, anyway.
I don't think that's true: For example, right before calling read() on the reader side, the pipe would have a reader that isn't actually reading.
You would typically just write to the pipe, or use select or poll. If you need a handshake mechanism you can do that out of band various ways or come up with and in-band protocol.
I don't know if there is a built-in way to know if a reader on the other end is blocking. Why do you need to know this?
If I recall correctly, you can not have a pipe with no reader which means that you have either a read(2) or a select(2) syscal pending at all time.

Resources