This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

1.7.7: stdio functions block each other in a multithreaded program


I am trying to make a multi-threaded application, where one thread reads
commands from stdin, and another thread is doing other things, such as
reading files and printing messages to stdout.

The problem I have is that the thread that reads files and writes to stdout
locks while the other thread is reading from stdin. To demonstrate this,
I created a small program that has this behavior. The C-code is present at
the end of this e-mail.

To compile: save this code as 'test.c', and type 'make test' (no Makefile
required). To execute, type './test'. As you can see in the source code, the
second thread copies the contents of test.c to stdout, and then it will
crash(*). The main thread will continuously read lines from stdin.

The point of this demo is: when started, the application will not
immediately crash, so somehow the second thread is being blocked by the
main thread. You will also notice that, each time when you type something
and press enter (in other words, each time when scanf returns in the main
thread), the second thread makes some progress in printing to stdout,
until the point where it crashes.

I noticed that the problem is really sensitive to what exactly happens in
the second thread. The second thread is not blocked if it prints something
to stdout without reading from a file, and reading from a file without
printing anything doesn't block either. The combination of the two seems
important. Even when I first open the file, read it and calculate its
checksum, and then write the checksum to stdout, it doesn't block.

I couldn't find any documentation on the threading behavior of stdio calls,
so I don't know whether this is intended behavior. If this documentation
exists, can you point me to it? I'd like to use it to find alternative
functions that are not affected by this blocking behavior.

Also, can you tell me how to achieve the goal I described in the first
paragraph? In the actual application, I can not really change how the second
thread reads files and writes to stdout, but I can use alternative ways for
reading stdin. Would it help to use low-level I/O functions (such as read)?

I have this problem in Cygwin 1.7.7. I can remember that the same
application worked fine in Cygwin 1.5.

(*) This is intentional: I wanted to find out whether the thread is really
blocked, or whether stdout was just not flushed to the terminal. I realize
now there are easier ways, but this was just how I did it.

/* test.c: */
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *threadfunc(void *arg)
{
	/* Read from file and write to stdout: */
	FILE *fp = fopen("./test.c", "rb");
	while(1)
	{
		int c = fgetc(fp);
		if(c == EOF) break;
		putchar(c);
	}
	fclose(fp);

	/* Trigger a crash: */
	*((char *)NULL) = 1;

	return NULL;
}

int main(int argc, char *argv[])
{
	pthread_t tid;
	pthread_create(&tid, NULL, threadfunc, NULL);

	/* Read from stdin: */
	char input[80];
	while(1)
		scanf("%s", input);

	return 0;
}

Attachment: cygcheck.out
Description: Binary data

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]