You are not logged in.

#1 2013-08-04 13:27:29

cmtptr
Member
Registered: 2008-09-01
Posts: 135

[solved] -std=foo causes different behavior in getchar(), SIGLARM

So as far as I can tell, there's no standard that dictates how getchar() and SIGALRM should interact - it seems that on some platforms SIGALRM breaks a blocking getchar() (returns EOF), and on some platforms it doesn't.  That's fine, as long as it's predictable so that I can code appropriately for a given platform.  But gcc on Arch Linux has thrown me a curveball:

#include <signal.h>
#include <stdio.h>
#include <sys/time.h>

static void timer_sigalrm(int sig)
{
	(void)sig;
	static int i;
	printf("%s i=%d\n", __FUNCTION__, i++);
	signal(SIGALRM, timer_sigalrm);
}

int main(void)
{
	signal(SIGALRM, timer_sigalrm);
	struct itimerval timer = {
		.it_interval = {1, 0},
		.it_value = {1, 0},
	};
	setitimer(ITIMER_REAL, &timer, 0);
	int c;
	while (c = getchar(), c != '\n') {
		static int i;
		printf("%s i=%d (c=0x%x)\n", __FUNCTION__, i++, c);
	}
	return 0;
}

And here's some output to demonstrate:

$ cc test.c 
$ ./a.out  # compiled with no flags, SIGALRM does not cause getchar() to return EOF
timer_sigalrm i=0
timer_sigalrm i=1
timer_sigalrm i=2
timer_sigalrm i=3

(This is how the same program behaves on FreeBSD, regardless of gcc's -std flag)

$ cc -std=c99 test.c 
$ ./a.out  # compiled with std=c99, SIGLARM does cause getchar() to return EOF
timer_sigalrm i=0
main i=0 (c=0xffffffff)
timer_sigalrm i=1
main i=1 (c=0xffffffff)
timer_sigalrm i=2
main i=2 (c=0xffffffff)
timer_sigalrm i=3
main i=3 (c=0xffffffff)

What??  Same platform, same compiler, different behavior.  As far as I can tell, it doesn't matter what you put after -std= to get the second behavior.  Can somebody please explain what I'm seeing here, and the recommended method for handling it?

Thanks.

Last edited by cmtptr (2013-08-05 21:13:22)

Offline

#2 2013-08-05 10:12:52

Trent
Member
From: Baltimore, MD (US)
Registered: 2009-04-16
Posts: 990

Re: [solved] -std=foo causes different behavior in getchar(), SIGLARM

If no behavior is mandated by any standard, your expectation that it should behave consistently was unfounded. Some Googling has suggested it might be part of POSIX but I can't find a specific reference.

If you can't find a guarantee of behavior, perhaps you should consider another way of achieving whatever it is you're trying to do.

Offline

#3 2013-08-05 10:43:48

progandy
Member
Registered: 2012-05-17
Posts: 5,184

Re: [solved] -std=foo causes different behavior in getchar(), SIGLARM

According to POSIX, getchar should be aborted with errno=EINTR when a signal arrives
http://manned.org/fgetc/958fb8aa?v=a
http://manned.org/getchar/3455027a?v=a

and the implementation on archlinux claims to conform to posix http://manned.org/gets.3

PS: a timed input is done in this manner:

set_dummy_alarm_signal_handler();
alarm( timeout );
c=getchar();
...

PPS: If you want your code to behave a certain way, then you have to choose a C(++) standard and adhere to it. So just specify it and all is well.

PPPS: I have one last remark: The signal handling seems to be a POSIX extension and is NOT part if ISO C.

Last edited by progandy (2013-08-05 21:56:33)


| alias CUTF='LANG=en_XX.UTF-8@POSIX ' |

Offline

#4 2013-08-05 21:12:55

cmtptr
Member
Registered: 2008-09-01
Posts: 135

Re: [solved] -std=foo causes different behavior in getchar(), SIGLARM

progandy wrote:

PS: a timed input is done in this manner:

set_dummy_alarm_signal_handler();
alarm( timeout );
c=getchar();
...

I know, but who said I was trying to do timed input?  wink
What I'm really doing is that I want to asynchronously poll something for the duration of my program.

progandy wrote:

PPS: If you want your code to behave a certain way, then you have to choose a C(++) standard and adhere to it. So just specify it and all is well.

I'm fine with that.  Then according to your first few sentences (that POSIX defines this behavior), it sounds like I need to be talking to the BSD guys to see why their getchar() doesn't break with EINTR, even when I use -std=c99.

Trent wrote:

If no behavior is mandated by any standard, your expectation that it should behave consistently was unfounded. Some Googling has suggested it might be part of POSIX but I can't find a specific reference.

If you can't find a guarantee of behavior, perhaps you should consider another way of achieving whatever it is you're trying to do.

It looks like this might end up happening, anyway.  I'm about to start moving to an epoll model so that I can interact with some other stuff, so I might as well toss stdin into the epoll mix and call it a day.

Thanks for the replies.  I'm going to mark this as solved per progandy's links.

Last edited by cmtptr (2013-08-05 21:14:22)

Offline

#5 2013-08-11 00:14:51

Trent
Member
From: Baltimore, MD (US)
Registered: 2009-04-16
Posts: 990

Re: [solved] -std=foo causes different behavior in getchar(), SIGLARM

I was on vacation earlier this week but I just thought I'd add that I don't think the linked pages imply that SIGALRM should abort getchar(). They do guarantee that if getchar (& friends) is interrupted by a signal, it fails with errno=EINTR, but say nothing about which specific signals are capable of interrupting it.

Also it seems you've already figured this out, but -std=whatever generally has no effect on POSIX compliance, only conformance to a C standard; i.e., -std=c11 will try to enforce the rules of the C11 language, but won't change the behavior of things that are specified by POSIX and not by C11.

Offline

#6 2013-08-17 13:18:07

cmtptr
Member
Registered: 2008-09-01
Posts: 135

Re: [solved] -std=foo causes different behavior in getchar(), SIGLARM

Trent wrote:

Also it seems you've already figured this out, but -std=whatever generally has no effect on POSIX compliance, only conformance to a C standard; i.e., -std=c11 will try to enforce the rules of the C11 language, but won't change the behavior of things that are specified by POSIX and not by C11.

This is what threw me, because what I'm observing directly conflicts with this.  Without any -std= specified, SIGALRM does not break getchar(), but with a -std= specified it does.  In accordance with the statement I quoted above, I would expect to see the same behavior with respect to POSIX signals regardless of the C standard I choose (or in this case, specify or don't specify).

Offline

#7 2013-08-18 01:55:35

Trent
Member
From: Baltimore, MD (US)
Registered: 2009-04-16
Posts: 990

Re: [solved] -std=foo causes different behavior in getchar(), SIGLARM

cmtptr wrote:
Trent wrote:

Also it seems you've already figured this out, but -std=whatever generally has no effect on POSIX compliance, only conformance to a C standard; i.e., -std=c11 will try to enforce the rules of the C11 language, but won't change the behavior of things that are specified by POSIX and not by C11.

This is what threw me, because what I'm observing directly conflicts with this.

My mistake; "won't change the behavior of" was misleading. I should have said "makes no guarantees about". Nevertheless, since C does not and POSIX doesn't seem to specify whether SIGALRM must break getchar(), what you're seeing does not in fact conflict with what I said.

Without any -std= specified, SIGALRM does not break getchar(), but with a -std= specified it does.

Because -std=whatever changes the behavior does not make any particular behavior part of the standard. Most likely the behavior changed as a side effect of some other difference in how gcc treats the two languages, even though both are acceptable "standard" behaviors

In accordance with the statement I quoted above, I would expect to see the same behavior with respect to POSIX signals regardless of the C standard I choose (or in this case, specify or don't specify).

When using C, one should learn not to expect such ridiculously sensible things! tongue Nevertheless I apologize for misleading you.

Offline

#8 2013-08-18 18:12:33

cmtptr
Member
Registered: 2008-09-01
Posts: 135

Re: [solved] -std=foo causes different behavior in getchar(), SIGLARM

Trent wrote:

Nevertheless I apologize for misleading you.

Not at all, I always appreciate your explanations.  You have on more than one occasion cleared up my misunderstandings with regard to standards and things like this.

Thanks for your help!

Offline

Board footer

Powered by FluxBB