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