This is the mail archive of the ecos-discuss@sourceware.org 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]

Re: sscanf() exception issue of C lib



Xiaochen Zhou 写道:
> Jonathan Larmour 写道:
>   
>> Xiaochen Zhou wrote:
>>   
>>     
>>> I try hard to check my code, but does not work. At last I browse the c
>>> lib code, and have some doubts with the
>>> language/c/libc/stdio/current/src/common/fflush.cxx
>>>
>>> // flush all but one stream
>>> externC Cyg_ErrNo
>>> cyg_libc_stdio_flush_all_but( Cyg_StdioStream *not_this_stream )
>>> {
>>>     
>>>       
>> [snip]
>>   
>>     
>>> (1) only initialize the files_flushed[0] , not all elements.
>>>     
>>>       
>> The C standard mandates that any initialiser causes any remaining elements
>> to be initialised to 0.
>>
>>   
>>     
> yeah, right.
>   
>>> (2) Cyg_libc_stdio_files::get_file_stream(i) is not safe here. I think
>>> it should need Cyg_libc_stdio_files::lock() &
>>> Cyg_libc_stdio_files::unlock() to protect.
>>>
>>> I'm not sure of this, can someone affirm? thanks!
>>>     
>>>       
>> Although I can't remember the details, you have to be careful in this code
>> to avoid deadlock. Is there any particular problem scenario you are hitting
>> as a result? Has your problem gone away if you add such a lock?
>>
>> Jifl
>>   
>>     
> I write a test thread to call sscanf() again and again in a loop, and in
> the same time, I hit the F5 to flush the web pages of my device very
> quickly (httpd has higher priority and call stdio lib's fdopen() and
> close()). The exception repeated in few minutes. So I'm sure it is a
> ecos lib c bug. Add the lock, after several hours testing, the exception
> is gone. But it is not the exact evidence. I will add some testing code
> to prove it today.
>
>   
Proved!!!
test code 1:

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

// Cyg_libc_stdio_files::lock();
stream = Cyg_libc_stdio_files::get_file_stream(i);

cyg_interrupt_disable(); -----------------------------> for beautiful
print format
diag_printf("flush-before %p\n",stream);
--------------------------------------> pre-print the pointer
cyg_interrupt_enable();

cyg_thread_delay(10); ----------------------------> easy to be preempted
by httpd

if ((stream == NULL) || (stream == not_this_stream)) {

files_flushed[i] = true;
} // if
else {
cyg_interrupt_disable();
diag_printf("flush %p\n",stream);
--------------------------------------> print the pointer
cyg_interrupt_enable();

test code 2:

externC FILE *fdopen( int fd, const char *mode ) __THROW
{
.............
f = fopen_inner( (cyg_stdio_handle_t)fd, open_mode, binary, append );
diag_printf("open %p\n",f);
-----------------------------------------------------> print the open
pointer

..........
}

test code 3:

externC int
fclose( FILE *stream ) __THROW
{
.........................
if (NULL == real_stream)
{
errno = EBADF;
return EOF;
}

diag_printf("close %p\n",stream);
-------------------------------------------------> print the close pointer

Cyg_libc_stdio_files::lock();
................
}

result:

open 0x00361110
open 0x003619a0
flush 0x001d4648
close 0x00361110
close 0x003619a0
open 0x00361680 -------------------> open stream
flush-before 0x00361680 -------------------> pre-flush the opened stream
close 0x00361680 -------------------> close strem
open 0x003612a8
close 0x003612a8
open 0x003612a8
close 0x003612a8
open 0x00361110
close 0x00361110
open 0x00361110
close 0x00361110
flush 0x00361680 ---------------------> flush closed stream
[ABORT DATA] Frame:
001EA84C: B8 16 36 00 70 44 00 00 80 0D 19 00 F0 77 2F 11 |..6.pD.......w/.|
001EA85C: B0 16 36 00 03 00 00 00 B8 16 36 00 00 00 00 00 |..6.......6.....|
001EA86C: C0 A8 1E 00 CC AB 1E 00 00 00 00 00 B8 A8 1E 00 |................|
001EA87C: 70 76 C4 34 9C A8 1E 00 60 E7 00 00 64 D9 00 00 |pv.4....`...d...|
001EA88C: 13 00 00 20 04 00 00 00 60 E7 00 00 9C A8 1E 00 |... ....`.......|
001EA89C: 80 16 36 00 03 00 00 00 0C 00 00 00 16 00 00 00 |..6.............|
001EA8AC: 08 A9 1E 00 BC A8 1E 00 2C A4 14 00 20 E7 00 00 |........,... ...|
001EA8BC: 01 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 |................|
Registers:
R0: 003616b8 00004470 00190d80 112f77f0 003616b0 00000003
R6: 003616b8 00000000 001ea8c0 001eabcc 00000000
FP: 001ea8b8, IP: 34c47670, SP: 001ea89c, LR: 0000e760, PC: 0000d964,
PSR: 20000
013
DBG: In level [0]
fun_addr entry = e710 , return addr(lr)=14a42c,fun_sp = 1ea8bc ,fp=1ea908
DBG: In level [1]
fun_addr entry = 14a308 , return addr(lr)=14ac80,fun_sp = 1ea90c ,fp=1ea930
DBG: In level [2]
fun_addr entry = 14ac08 , return addr(lr)=14c7bc,fun_sp = 1ea934 ,fp=1eabc8
DBG: In level [3]
fun_addr entry = 14b6b4 , return addr(lr)=14b4e8,fun_sp = 1eabcc ,fp=1eac2c
DBG: In level [4]
fun_addr entry = 14b4a0 , return addr(lr)=14a544,fun_sp = 1eac30 ,fp=1eac3c
DBG: In level [5]
fun_addr entry = 14a52c , return addr(lr)=30820,fun_sp = 1eac4c ,fp=1eac88
DBG: In level [6]
fun_addr entry = 307d4 , return addr(lr)=3c100,fun_sp = 1eac8c ,fp=1ead78
DBG: In level [7]
fun_addr entry = 3bfb0 , return addr(lr)=c534,fun_sp = 1ead7c ,fp=1ead8c
DBG: In level [8]
fun_addr entry = c50c , return addr(lr)=c50c,fun_sp = 1ead90 ,fp=deadbeef
Reached the end of stack!
Exception handler returned!

> The deadlock is the problem. I'm not familiar with the c lib code, so I
> need expert to help. Thanks!
>
>   



-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss


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