Unix Programming - Strange outputting order

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > July 2006 > Strange outputting order





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author Strange outputting order
Mounir

2006-07-26, 1:26 pm

Hi,

Here is a piece of source code :

printf("\n\t... Message ")
// [...]
printf("\n\nShared Memory...\n"
"\t ... segment shmid ");

if ((shmid=shmget(MemBase,0,0)) == -1)
{
perror(NULL);
exit(3);
}

And Strace output :

write(1, "\t... Message \n"..., 53 ... Message

Shared Memory...
) = 53
shmget(2073102904, 0, 0) = -1 ENOENT (No such file or
directory)
dup(2) = 3
fcntl64(3, F_GETFL) = 0x8001 (flags
O_WRONLY|O_LARGEFILE)
close(3) = 0
write(2, "No such file or directory\n", 26No such file or directory
) = 26
write(1, "\t ... segment shmid ", 20) = 20

I don't understand why shmget() is executed before the printing of
"\t... segment shmid". Is this because of tabulation character ? I hope
have been comprehensible...

Lew Pitcher

2006-07-26, 1:26 pm

Hi, Mounir

Please see my comments, inline


Mounir wrote:
> Hi,
>
> Here is a piece of source code :
>
> printf("\n\t... Message ")
> // [...]
> printf("\n\nShared Memory...\n"
> "\t ... segment shmid ");


To answer your question below, the above printf() is the cause of your
quandry.
printf() does not write directly to the output device but instead
writes to a buffer that is periodically flushed (written) to the output
device automatically. The flush rules are fairly simple:
When stdout is directed to a device, flush the buffer when
a) a newline is presented, or
b) when the buffer becomes full, or
c) when an explicit fflush() is executed, or
d) when the process terminates

When stdout is directed to a file, flush the buffer when
a) when the buffer becomes full, or
b) when an explicit fflush() is executed, or
c) when the process terminates

Your printf() streamed out a block of data that conformed to the first
rule for device output ("flush when a newline is presented"), followed
by another block of data that was not terminated with a newline.
Because it lacked a newline, this meant that the block of data would
not be flushed until either the buffer became full (didn't happen), or
fflush() was invoked (didn't happen) or the process terminated (*that's
the ticket*). So, your second block of output ("\t ... segment shmid ")
didn't get written by stdio to the device until the program ended,
despite the fact that your logic wrote it /to the buffer/ much earlier.


> if ((shmid=shmget(MemBase,0,0)) == -1)
> {
> perror(NULL);
> exit(3);


OK, at this point, the process has executed shmget(), received an error
condition, written an error msg to stderr, and invoked exit().

Remember, you still have a block of stdout buffered output waiting to
be flushed from the buffer to the device ("\t ... segment shmid ").
Now, after the shmget() has executed, exit() will flush this out to the
device with a write() call.

Thus, your sequence of events is explained.

> }
>
> And Strace output :
>
> write(1, "\t... Message \n"..., 53 ... Message
>
> Shared Memory...
> ) = 53
> shmget(2073102904, 0, 0) = -1 ENOENT (No such file or
> directory)
> dup(2) = 3
> fcntl64(3, F_GETFL) = 0x8001 (flags
> O_WRONLY|O_LARGEFILE)
> close(3) = 0
> write(2, "No such file or directory\n", 26No such file or directory
> ) = 26
> write(1, "\t ... segment shmid ", 20) = 20
>
> I don't understand why shmget() is executed before the printing of
> "\t... segment shmid". Is this because of tabulation character ? I hope
> have been comprehensible...


Bjorn Reese

2006-07-26, 1:26 pm

Mounir wrote:

> printf("\n\nShared Memory...\n"
> "\t ... segment shmid ");
>
> if ((shmid=shmget(MemBase,0,0)) == -1)
> {
> perror(NULL);
> exit(3);
> }


> shmget(2073102904, 0, 0) = -1 ENOENT (No such file or
> directory)
> dup(2) = 3
> fcntl64(3, F_GETFL) = 0x8001 (flags
> O_WRONLY|O_LARGEFILE)
> close(3) = 0
> write(2, "No such file or directory\n", 26No such file or directory
> ) = 26
> write(1, "\t ... segment shmid ", 20) = 20
>
> I don't understand why shmget() is executed before the printing of
> "\t... segment shmid". Is this because of tabulation character ? I hope
> have been comprehensible...


The printf output is buffered, so it is only sent to stdout (via write)
when the buffer is full, or when to buffer is flushed (which in your
case seems to happen when you exit the program).

Try to insert an "fflush(stdout);" statement after your printf
statement.

--
mail1dotstofanetdotdk
Mounir

2006-07-27, 7:28 am

Thank you (and Bjorn Reese too) for your accurate and detailed answers.

> To answer your question below, the above printf() is the cause of your
> quandry.
> printf() does not write directly to the output device but instead
> writes to a buffer that is periodically flushed (written) to the output
> device automatically. [...]


Err... Yes.
..=2E. A bit tired when I posted my question :-p. Now it works. Concerning
the behaviour ofbuffering functions (printf, etc.) , they can determine
if stdout is attached (dup2() ?) to a file or to a device ?

Moreover I was disturbed by the behaviour of perror(). Is stderr an
auto-flushed device ? Or does the process flush stderr before stdout
when it terminates ?

Regards,

--
Mounir A=EFt Tahar

Lew Pitcher

2006-07-27, 1:27 pm

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


Mounir wrote:
> Thank you (and Bjorn Reese too) for your accurate and detailed answers.
>
>
> Err... Yes.
> ... A bit tired when I posted my question :-p. Now it works. Concerning
> the behaviour ofbuffering functions (printf, etc.) , they can determine
> if stdout is attached (dup2() ?) to a file or to a device ?


Yes, the buffered I/O routines check (at open() time, as I understand
it) to see if the target is a device or a file. They probably use the
isatty(3) or stat(2) call to make this determination.

> Moreover I was disturbed by the behaviour of perror(). Is stderr an
> auto-flushed device ?


Yes. Any stdio (fopen()/fprintf()/fclose()) activity is handled the
same way. stderr is just another stdio stream in that sense, and
buffered output to it will be flushed under the same conditions and
with the same rules as any other stdio stream. This behaviour is
specified as part of both the Posix/SUS and C standards.

> Or does the process flush stderr before stdout
> when it terminates ?


I don't know the order in which exit(3) or program termination flushes
buffered output streams. I don't think that the order is specified in
any standard, although I could be wrong.

HTH
- --
Lew Pitcher


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (MingW32) - WinPT 0.11.12

iD8DBQFEyLiLagVFX4UWr64RApYAAKCYIbN2XwCL
G7yP7eu6Va456ZPowwCg781M
61Zcq1ogQWuTVDhB7c07VHk=
=A2AZ
-----END PGP SIGNATURE-----

Barry Margolin

2006-07-27, 7:24 pm

In article <1154005136.933798.56080@i42g2000cwa.googlegroups.com>,
"Lew Pitcher" <lpitcher@sympatico.ca> wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
>
> Mounir wrote:
>
> Yes. Any stdio (fopen()/fprintf()/fclose()) activity is handled the
> same way. stderr is just another stdio stream in that sense, and
> buffered output to it will be flushed under the same conditions and
> with the same rules as any other stdio stream. This behaviour is
> specified as part of both the Posix/SUS and C standards.


Actually, I think Mounir was correct. According to my stdio(3) man page:

Initially, the standard error stream is unbuffered; the standard
input and output streams are fully buffered if and only if the
streams do not refer to an interactive or ``terminal'' device, as
determined by the isatty(3) function. In fact, all freshly-opened
streams that refer to terminal devices default to line buffering,
and pending output to such streams is written automatically
whenever such an input stream is read.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
Mounir

2006-07-28, 7:27 am

> Actually, I think Mounir was correct.

Yeah, but it's just a coincidence : I didn't notice that perror() puts
a newline when I said that, so even if it was buffered, stderr output
would be displayed before stdout in my programm ^^

> Initially, the standard error stream is unbuffered;


So stderr isn't buffered. Therefore, stderr doesn't need to be fflushed
at exit... Right ?

--=20
Mounir A=EFt Tahar

Barry Margolin

2006-07-29, 1:23 am

In article <1154074876.958229.60240@i42g2000cwa.googlegroups.com>,
"Mounir" <downwater@gmail.com> wrote:

>
> Yeah, but it's just a coincidence : I didn't notice that perror() puts
> a newline when I said that, so even if it was buffered, stderr output
> would be displayed before stdout in my programm ^^
>
>
> So stderr isn't buffered. Therefore, stderr doesn't need to be fflushed
> at exit... Right ?


It doesn't need to be flushed *ever*. So obviously it doesn't need to
be flushed at exit, either.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com