[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

strange Fselect/Finstat behaviour...



 Hope anyone out there has had a good start into the new year...

 Mine was a bit nervous, because while I was trying to get my head back
into a more comfortable state after the New Years Eve party it was once
again hit by a severe programming problem. Obviously it wasn't the perfect
time for this problem to arise, so I didn't really manage to track it down.

 I was trying to improve my `talk' program, which puts the current device
into RAW mode to be able to read keys like ^C for example, which then get
sent through a pipe to inform the remote partner that a connection is to
be shut down.

 Knowing that Fselect() only really works on pipes or the `real' console
device, but not on other devices, I used Fselect(50, &rfd, 0L, 0L) to not
spend too much time in a busy-poll loop and still be able to use it for
tty input. Since the corresponding tty is in RAW mode, I'd expect it to
give me a 0x03 from Fread() when ^C is pressed. Instead, the process got
the SIGINT signal and was killed all the time.

 When trying not to use Fselect() at all for tty input, but just for pipe
input with a timeout, and later manually check the tty with Finstat() I got
the same result. Since a RAW Fread() will return for every char regardless
how many you ordered, but not if there isn't one at all, I ran out of clues
on how to check the tty input without blocking and changed my program to
catch SIGINT instead of reading it from the tty so it now more or less
does what I want.

 But the problem remains and if you'd like to check it, then run:

/*
 *	murphy on the road again...
 */

#include <ioctl.h>
#include <mintbind.h>
#include <signal.h>
#include <stdio.h>

void catch(long sig)
{
	printf("hit by SIGINT\r\n");
}

void main()
{
	struct sgttyb	tty;
	long		rfd;
	char		c;

	Psignal(SIGINT, catch);

	ioctl(0, TIOCGETP, &tty);
	tty.sg_flags = RAW;
	ioctl(0, TIOCSETP, &tty);

	for (;;) {
#if 1
		if (Finstat(0)) {
#else
		rfd = 1;
		(void)Fselect(50, &rfd, 0L, 0L);
		if (rfd) {
#endif
			Fread(0, 1L, &c);
			printf("key = %i\r\n", c);
		}
	}
}

 If you do so, you'll have to face the strange fact that the _first_ ^C will
raise the signal, whereas every following one will read as 0x03 from the
Fread() call.

 A pure:

for (;;) {
	Fread(0, 1L, &c);
	printf("key = %i\r\n", c);
}

 won't do this but report 0x03 for every ^C instead, just like you and I
might have expected it, but gives you no possibility to do other things
if there isn't any input at all.

 All this happenes with MiNT 1.09 plus no patches except the nalloc stuff
and my own ones dealing with the biosfs and the sticky bit AND the original
MiNT 1.04. Allthough I may have very well missed some patches cause I don't
save them all if I think I don't need them, but prefer to wait for the next
official update instead, I consider this being a `new' problem.

 So has anyone got the faintest idea what this is meant to say me? Looks
like the combination of dev->ioctl(FIONREAD) and/or dev->select affects the
process' signal stuff in a very bad way, but before I try to get through
this I'd like to have it discussed here.

so long,
TeSche
--
PS: If the above written looks weird, then that's probably because it _is_.
WhoDunnIt: Torsten Scherer (Schiller, Tesche, ...)
Where: Faculty of Technology, University of Bielefeld, Germany
EMail: itschere@techfak.uni-bielefeld.de / tesche@hrz.uni-bielefeld.de