This is the mail archive of the ecos-bugs@sources.redhat.com mailing list for the eCos 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]

[Bug 21904] New: bugs in stdio stream


http://bugs.ecos.sourceware.org/show_bug.cgi?id=21904

           Summary: bugs in stdio stream
           Product: eCos
           Version: 1.3.1
          Platform: pc (i386 PC target)
        OS/Version: IA32
            Status: UNCONFIRMED
          Severity: normal
          Priority: low
         Component: Other
        AssignedTo: jifl at ecoscentric dot com
        ReportedBy: anonymous at sourceware dot cygnus dot com


Hello, everyone!
I've been working on eCos for a period of time. It's an 
elaborate work; still, a few bugs were found.

1 At the beginning of Cyg_StdioStream::flush_output_unlocked() 
in stream.cxx, there are codes as follows:
    // first just check that we _can_ write to the device!
    if ( !flags.opened_for_write )
        return EINVAL;

  That means we can never flush a stream opened for read. But at 
the beginning of cyg_libc_stdio_flush_all_but() in fflush.cxx, 
such codes are found:

        for (i=0; (i<FOPEN_MAX) && !err; i++) {
            if (files_flushed[i] == false) {
                
                stream = Cyg_libc_stdio_files::get_file_stream
(i);

*               if ((stream == NULL) || (stream == 
not_this_stream)) {
                    // if it isn't a valid stream, set its entry 
in the
                    // list of files flushed since we don't want 
to
                    // flush it
                    // Ditto if its the one we're meant to miss
                    
                    files_flushed[i] = true;
                } // if
                else {
                    // valid stream
                    
                    if ( stream->trylock_me() ) {
                        err = stream->flush_output_unlocked();
                        stream->unlock_me();
                        files_flushed[i] = true;
                    } // if
                    else
                        loop_again = true;
                } // else
            } // if
        } // for

  That means only flushing of null stream or the current stream 
is prevented. If there are two streams opened for read, they may 
flush one another during the loop. Then 
Cyg_StdioStream::flush_output_unlocked() will return EINVAL!
  I've modified the line with a '*' ahead like this:
                if ((stream == NULL) || (stream == 
not_this_stream) || (stream->get_stream_rw() == 
Cyg_StdioStream::CYG_STREAM_READ)) {

  The following is the implementation of 
Cyg_StdioStream::get_stream_rw() added to stream.inl:

inline Cyg_StdioStream::OpenMode
Cyg_StdioStream::get_stream_rw( void )
{
	if (flags.opened_for_read && flags.opened_for_write)
		return CYG_STREAM_READWRITE;
	else
	{
		if (flags.opened_for_write)
			return CYG_STREAM_WRITE;
		else
			return CYG_STREAM_READ;
	}
}

  I'm not sure whether my modification is proper.



2 When Cyg_StdioStream::refill_read_buffer() is called, the 
following condition is always satisfied, such as the case in 
fgets.cxx:

    if (!err && !bytes_read) { // if no err, but nothing to 
read, try again
        real_stream->refill_read_buffer();
        ......

  So, I think io_buf.drain_buffer() should be called in 
Cyg_StdioStream::refill_read_buffer(). In fact, even a simple 
test as follows can't be passed without calling 
io_buf.drain_buffer().

// Begin of the test file
#include <cyg/kernel/kapi.h>
#include <stdio.h>

#define STACKSIZE (16*1024)
char thread_stack[1][STACKSIZE];

cyg_thread thread[1];
cyg_handle_t thread_handle[1];

void io(void);

void io(void)
{char c;
	for (;;)
	{
		c = getchar();
		putchar(c);
	}
}

void cyg_start(void )	
{cyg_addrword_t i=0;
	cyg_thread_create(30, io, i, "io",
		(void *)(&thread_stack[i]), STACKSIZE,
		&thread_handle[i], &thread[i]);
	
	cyg_thread_resume(thread_handle[i]);
	cyg_scheduler_start();
} 
// End of the test file

  In the test, if you set CYGNUM_LIBC_STDIO_BUFSIZE as 256, you 
may type a string of 250 characters followed by 'CR' at the 
first getchar(). Then, you may type another string of 6 
characters to see what will happen.



3 In the generated heaps.cxx, I found the declaration of 
cygmem_pool_heap1 should be as follows, or the priority of it's 
constructor will be 65535 instead of 49900.

Cyg_Mempool_dlmalloc cygmem_pool_heap1 CYGBLD_ATTRIB_INIT_BEFORE
(CYG_INIT_LIBC) = Cyg_Mempool_dlmalloc ( (cyg_uint8 *)
CYGMEM_SECTION_heap1 , CYGMEM_SECTION_heap1_SIZE );

  I'm not sure whether it is due to our obsolete GCC.

---------------------------------------------------------------------------

Originator:
Jing Xiong

Organization:
Institute of Computer Technology of Academy in China

Unformatted:
Originator:  

page: sourceware.cygnus.com/ecos/problemreport.html

Send_PR_form: Sent_from_sourceware.cygnus.com



------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.


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