Does fgets() locks stdout preventing printf - c

I have a C program with two threads one of those threads is almost all the time blocked in a fgets() waiting for user input. The second thread may need to print to the terminal while the first one is blocked on fgets().
From my tests it seems that the program waits for the fgets() on the first thread to return and then the second thread can print.
Is this who it works or could I print while the the other thread is blocked on the fgets()?
This implementations runs on eCos (embedded Configurable operating system).
Thread locked on fgets():
int my_getline (char** argv, int argvsize)
{
static char line[MAX_LINE];
char *p;
int argc;
fgets(line, MAX_LINE, stdin);
for (argc=0,p=line; (*line != '\0') && (argc < argvsize); p=NULL,argc++) {
p = strtok(p, " \t\n");
argv[argc] = p;
if (p == NULL) return argc;
}
argv[argc] = p;
return argc;
}
Thread trying to print:
while(1){
unsigned char bufr[50];
read_until(bufr);
if (bufr[1] == (unsigned char)NMFL ){
cyg_mutex_lock(&scree_mtx);
printf("Memory half full!\n");
cyg_mutex_unlock(&scree_mtx);
continue;
}
cyg_mbox_put( mbx_serial_userH, bufr );
}
Output (I'm sure the message was there before):

The C standard does not specify any association at all between the standard input stream and the standard output stream. In particular, it does not specify that one thread blocking on reading from standard input, via any standard function, should cause any output function to block.
HOWEVER, the standard also does not say the opposite, that a thread blocking on input input from stdin must not cause another to block on output to stdout. Whether that happens would be a function of the C implementation, and probably of the specific devices with which stdin and stdout are associated.
You appear to be using a Windows C implementation with stdin and stdout both connected to a CMD.EXE window. Windows has a lot of idiosynchrasies, and I'm inclined to guess that the blocking you observe is one of them. I would not expect the same on Linux or OSX, but that does not mean it is erroneous.

Related

Detecting Ctrl-D in C

I am trying to detect the Ctrl+D user input, which I know returns EOF. Right now, I know the code waits for input from the stdin stream, but is there a way to let the program continue until the Ctrl+D command is in stdin? The program should continue running past the if statement if Ctrl+D isn't inputted.
char buffer[];
if (fgets(buffer, 10, stdin) == NULL{
//write to file
}
You want to stop your program when the user presses Ctrl+D without actually reading stdin? In this case, you should consider using Ctrl+C instead. But first I will write something about non-blocking I/O, since this is what you are asking for.
There is no way to achieve nonblocking I/O in standard C. However, you could use POSIX-functions like select or fcntl in combination with read. There are other questions about it on StackOverflow which should provide all information you need. This question for example.
If you want to handle Ctrl+C instead, you can use thesignal function:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
volatile bool shouldRun = true;
void sighandler(int) {
shouldRun = false;
}
int main(int argc, char *argv[]) {
if (signal(SIGINT, &sighandler) == SIG_ERR) {
fprintf(stderr, "Could not set signal handler\n");
return EXIT_FAILURE;
}
printf("Program started\n");
while (shouldRun) {
// Do something...
}
printf("Program is shutting down.\n");
return EXIT_SUCCESS;
}
Note that signal handlers (i.e. sighandler) might interrupt your thread at any moment. This means they are prone to race conditions. You must even avoid acquiring any locks within a signal handler. This means just calling printf within a signal handler can cause a deadlock. Just setting boolean flags as shown in the example is fine, though. There are solutions like signal masks and the self pipe trick to circumvent these limitations, but they should not be necessary here.
Since the machine generates EOF on Ctrl+D, you should be checking fgets() for NULL, as fgets() is obliged to return NULL on end of file.
line = fgets(l, BUFFSIZE, stdin)
if (line == NULL)
continue;
On most operating systems, stdin is buffered one line at a time, and any attempt to read it (without going into low-level nasties) will stop until either a line or EOF is available. If you don't mind this, and just want to check for EOF without reading-in any waiting input if EOF is not present, you could use ungetc:
#include <stdio.h>
int check_for_EOF() {
if (feof(stdin)) return 1;
int c = getc(stdin);
if (c == EOF) return 1;
ungetc(c, stdin);
}
int main() {
printf("Start typing:\n");
while (!check_for_EOF()) {
int bytes_typed = 0;
while (getchar() != '\n') bytes_typed++;
printf("You typed a line of %d bytes\n", bytes_typed);
}
printf("You typed EOF\n");
}
You are only guaranteed one character of push-back from ungetc, although most implementations give you much more. And it works only if you're not going to seek the stream later (which is the case with stdin). Notice also that I'm calling it "bytes typed", not "characters typed": Chinese, Japanese and Korean characters for example cannot fit into the char type of most C implementations, and it would depend how the console encodes them when you type (if you have a CJK input method set up or can copy/paste some, you can try it on the above program and see).
It is too much to post here and you are not specific what you have currently and what you want. So here gives you a general idea of how to do it:
Put that if statement inside a forked process or other thread
Send a posix signal to your (parent) process when the key is captured
Add signal handler in your program
If you just wanna terminate the program when C-d is entered, just send a SIGKILL in step 2 and ignore step 3.
If you do not know any term above, Google is your friend

c pipe read string is empty

I just want to create 2 new forks(child processes) and they will put their name sequentally. SO first they need to some string in pipe to check something. Let's see the code:
char myname[] = "ALOAA";
int main ()
{
int fds[2];
pid_t pid;
pipe(fds);
pid = fork();
if(pid == 0)
{
strcpy(myname, "first");
}
else
{
pid = fork();
if(pid == 0)
{
strcpy(myname, "second");
}
}
if(strcmp(myname, "ALOAA") != 0)
{
char readbuffer[1025];
int i;
for (i = 0; i < 2 ; i++)
{
//printf("%s\n", myname);
close(fds[0]);
write(fds[1], myname, strlen(myname));
while(1)
{
close(fds[1]);
int n = read(fds[0], readbuffer, 1024);
readbuffer[n] = 0;
printf("%s-alihan\n", readbuffer);
if(readbuffer != myname)
break;
sleep(1);
}
//printf("%s\n", myname);
}
}
return 0;
}
So the first process will write her name to pipe. And after that, will check if any new string in pipe. It will be same for second too. However I got empty string from read() function. So it prints like that
-alihan
-alihan
I couldn't get the problem.
However I got empty string from read() function [...] I couldn't get the problem.
#MikeCAT nailed this issue with his observation in comments that each child closes fds[0] before it ever attempts to read from it. No other file is assigned the same FD between, so the read fails. You do not test for the failure.
Not testing for the read failure is a significant problem, because your program does not merely fail to recognize it -- it exhibits undefined behavior as a result. This arises for (at least) two reasons:
read() will have indicated failure by returning -1, and your program will respond by attempting an out-of-bounds write (to readbuffer[-1]).
if we ignore the UB resulting from (1), we still have the program thereafter reading from completely uninitialized array readbuffer (because neither the read() call nor the assignment will have set the value of any element of that array).
Overall, you need to learn the discipline of checking the return values of your library function calls for error conditions, at least everywhere that it matters whether an error occurred (which is for most calls). For example, your usage of pipe(), fork(), and write() exhibits this problem, too. Under some circumstances you want to check the return value of printf()-family functions, and you usually want to check the return value of input functions -- not just read(), but scanf(), fgets(), etc..
Tertiarily, your usage of read() and write() is incorrect. You make the common mistake of assuming that (on success) write() will reliably write all the bytes specified, and that read() will read all bytes that have been written, up to the specified buffer size. Although that ordinarily works in practice for exchanging short messages over a pipe, it is not guaranteed. In general, write() may perform only a partial write and read() may perform only a partial read, for unspecified, unpredictable reasons.
To write successfully one generally must be prepared to repeat write() calls in a loop, using the return value to determine where (or whether) to start the next write. To read complete messages successfully one generally must be prepared similarly to repeat read() calls in a loop until the requisite number of bytes have been read into the buffer, or until some other termination condition is satisfied, such as the end of the file being reached. I presume it will not be lost on you that many forms of this require advance knowledge of the number of bytes to read.

Can I access stdin without keyboard?

I have compiled the following code with gcc
int main() {
int a = 0;
fprintf( stdin, "%d", 123 );
fscanf( stdin, "%d", &a );
printf( "%d\n", a );
return 0;
}
In my expectation, the program should executes straightly (i.e., the program never pause and wait for user input). But it still stop, and wait for my input.
I want to know what happen when I try to write something to stdin and how to modify this code and it can execute straightly?
stdin is for input only, stdout is for output. (4566976's answer shows you what happens when you try to output to stdin) See for example the glibc documentation on standard streams
(in short, writing to stdin makes no sense at all)
If you print out the return value of fprintf(stdin you can see that the function call fails.
In the shell you can pipe something into the stdin of the process.
#include <stdio.h>
int main(void) {
int a = 0, ret;
printf("%d\n", ret = fprintf( stdin, "%d", 123 ));
if (ret < 0) perror("fprintf");
fscanf( stdin, "%d", &a );
printf( "%d\n", a );
return 0;
}
$ echo 123 | ./a.out
-1
fprintf: Bad file descriptor
123
$
In addition of the fprintf(stdin, bug you also forgot that stdin is not the keyboard. The latest C11 standard does not know about the keyboard. On a Linux graphical desktop, only the X11 server is reading from the physical keyboard.
Practically speaking, on POSIX systems notably such as Linux, stdin can be a pipe(7) (using pipelines in your shell is very common), a fifo(7), a socket(7), a plain file (thru redirection) or even /dev/null, and of course also a terminal.
The funny thing these days is that terminals are very often virtual emulated devices (I did not see any real physical terminal in this century, outside of museums), read about pseudotty. The details are quite arcane for historical reasons. Read the tty demystified page. See also ANSI escape code wikipage & console_codes(4) and tty(4) (so consider /dev/tty and perhaps /dev/console)
You can check (with isatty(3)) that stdin is a terminal (actually a pseudotty) using isatty(STDIN_FILENO)...
Practically speaking, when you really want to use the terminal, I strongly recommend using a library like ncurses or GNU readline (both are using termios(3))
Don't forget that I/O is generally buffered, and use fflush(3) wisely.
BTW, you should have compiled with all warnings & debug info (gcc -Wall -Wextra -g) then use the gdb debugger. And strace(1) would have been very useful too.
Maybe you wanted to pipe to your own program (but that is weird, and often wrong, unless you take great care about all the implications; it is however a very useful trick for handling signal(7) in event oriented programs, notably those with some GUI). Beware that pipes have a limited buffer size (so avoid deadlocks, probably by having your event loop with poll(2)) and read about PIPE_BUF and write. You might have tried:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
int pfd[2] = {-1,-1};
int a= 0;
if (pipe(pfd)) { perror("pipe"); exit (EXIT_FAILURE); };
if (dup2(pfd[0],STDIN_FILENO)<0)
{ perror("dup2 stdin"); exit(EXIT_FAILURE);};
if (dup2(pfd[1],STDOUT_FILENO)<0)
{ perror("dup2 stdout"); exit(EXIT_FAILURE);};
if (printf("%d\n", 123)<=0) { perror("printf"); exit(EXIT_FAILURE); };
if (fflush(stdout)) { perror("fflush"); exit(EXIT_FAILURE); };
if (scanf("%d", &a)<1) { perror("scanf"); exit(EXIT_FAILURE); };
if (a != 123) { fprintf(stderr, "impossible happened a=%d\n", a); };
fprintf(stderr, "done...got a=%d\n", a);
}
You should read Advanced Linux Programming and learn more about syscalls(2); it has several chapters related to this. Read carefully pipe(2) and dup2(2) and be aware that the above program would be wrong for a larger output (bigger that PIPE_BUF, which on my system is several kilobytes)
BTW, you can get a readable FILE* from a memory buffer using fmemopen(3). For writing (e.g. with fprintf) to an output buffer, consider open_memstream and don't forget to fflush it before accessing the output buffer.
You can ungetc() a few characters and then read them with fscanf().
#include <stdio.h>
int main()
{
int value = 0;
ungetc ( '\n', stdin);//reverse order. newline first here but last from fscanf
ungetc ( '3', stdin);
ungetc ( '2', stdin);
ungetc ( '1', stdin);
fscanf ( stdin, "%d", &value);
printf ( "value is %d\n", value);
return 0;
}
output: value is 123
You're simply incorrect thinking that fscanf(stdin, "format", ...); does not block and wait for input, because it does.

Confusion about how a getchar() loop works internally

I've included an example program using getchar() below, for reference (not that anyone probably needs it), and feel free to address concerns with it if you desire. But my question is:
What exactly is going on when the program calls getchar()?
Here is my understanding (please clarify or correct me):
When getchar is called, it checks the STDIN buffer to see if there is any input.
If there isn't any input, getchar sleeps.
Upon wake, getchar checks to see if there is any input, and if not, puts it self to sleep again.
Steps 2 and 3 repeat until there is input.
Once there is input (which by convention includes an 'EOF' at the end), getchar returns the first character of this input and does something to indicate that the next call to getchar should return the second letter from the same buffer? I'm not really sure what that is.
When there are no more characters left other than EOF, does getchar flush the buffer?
The terms I used are probably not quite correct.
#include <stdio.h>
int getLine(char buffer[], int maxChars);
#define MAX_LINE_LENGTH 80
int main(void){
char line[MAX_LINE_LENGTH];
int errorCode;
errorCode = getLine(line, sizeof(line));
if(errorCode == 1)
printf("Input exceeded maximum line length of %d characters.\n", MAX_LINE_LENGTH);
printf("%s\n", line);
return 0;
}
int getLine(char buffer[], int maxChars){
int c, i = 0;
while((c = getchar()) != EOF && c != '\n' && i < maxChars - 1)
buffer[i++] = c;
buffer[i++] = '\0';
if(i == maxChars)
return 1;
else
return 0;
}
Step 2-4 are slightly off.
If there is no input in the standard I/O buffer, getchar() calls a function to reload the buffer. On a Unix-like system, that normally ends up calling the read() system call, and the read() system call puts the process to sleep until there is input to be processed, or the kernel knows there will be no input to be processed (EOF). When the read returns, the code adjusts the data structures so that getchar() knows how much data is available. You description implies polling; the standard I/O system does not poll for input.
Step 5 uses the adjusted pointers to return the correct values.
There really isn't an EOF character; it is a state, not a character. Even though you type Control-D or Control-Z to indicate 'EOF', that character is not inserted into the input stream. In fact, those characters cause the system to flush any typed characters that are still waiting for 'line editing' operations (like backspace) to change them so that they are made available to the read() system call. If there are no such characters, then read() returns 0 as the number of available characters, which means EOF. Then getchar() returns the value EOF (usually -1 but guaranteed to be negative whereas valid characters are guaranteed to be non-negative (zero or positive)).
So basically, rather than polling, is it that hitting Return causes a certain I/O interrupt, and then when the OS receives this, it wakes up any processes that are sleeping for I/O?
Yes, hitting Return triggers interrupts and the OS kernel processes them and wakes up processes that are waiting for the data. The terminal driver is woken by the kernel when interrupt occurs, and decides what to do with the character(s) that were just received. They may be stashed for further processing (canonical mode) or made available immediately (raw mode), etc. Assuming, of course, that the input is a terminal; if the input is from a disk file, it is simpler in many ways — or if it is a pipe, or …
Nominally, it isn't the terminal app that gets woken by the interrupt; it is the kernel that wakes first, then the shell running in the terminal app that is woken because there's data for it to read, and only when there's output does the terminal app get woken.
I say 'nominally' because there's an outside chance that in fact the terminal app does mediate the I/O via a pty (pseudo-tty), but I think it happens at the kernel level and the terminal application is involved fairly late in the process. There's a huge disconnect really between the keyboard where you type and the display where what you type appears.
See also Canonical vs non-canonical terminal input.

Can I parse ngrep's output with popen()?

I tried running this code, but nothing is ever shown. (Yes, I ran it as root) If I can't get ngrep's output I guess I'll try to figure out how to use libpcap with c++ although I haven't been able to find any good examples.
int main(void)
{
FILE* fproc = popen("ngrep -d wlan0 GET");
char c;
do {
printf("%c", fgetc(fproc));
} while (c!=EOF);
}
So what about this code causes nothing to be show, and what do you suggest to easily parse ngrep's output, or some other way of capturing GET requests, maybe with libpcap
I see the possible potential problems:
You have no open mode for the popen call? Leaving this off is likely to result in either a core dump or a random value of the stack deciding whether it's a read or write pipe.
The c variable should be an int rather than a char since it has to be able to hold all characters plus an EOF indicator.
And, you're not actually assigning anything to c which would cause the loop to exit.
With that do loop, you're trying to output the EOF to the output stream at the end. Don't know off the top of my head if this is a bad thing but it's certainly not necessary.
Try this:
int main(void) {
int ch;
FILE* fproc;
if ((fproc = popen("ngrep -d wlan0 GET", "r")) < 0) {
fprintf (stderr, "Cannot open pipe\n");
return 1;
}
while ((ch = fgetc (fproc)) != EOF) {
printf ("%c", ch);
};
pclose (fproc);
return 0;
}
You should also be aware that the pipe is fully buffered by default so you may not get any information until the buffer is full.

Resources