From 84b90e00f036a54e0c073c157f7ef723830657f3 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Mon, 9 Nov 2020 13:32:59 +0800 Subject: [PATCH] libc/stdio: Preallocate the stdin, stdout and stderr to handle the uninitialized stdin/stdout/stderr gracefully report here: https://github.com/apache/incubator-nuttx/issues/2203 Signed-off-by: Xiang Xiao --- fs/vfs/fs_fdopen.c | 96 +++++++++++++++++-------------------- include/nuttx/fs/fs.h | 4 ++ include/stdio.h | 6 +-- libs/libc/misc/lib_stream.c | 17 +++++++ 4 files changed, 69 insertions(+), 54 deletions(-) diff --git a/fs/vfs/fs_fdopen.c b/fs/vfs/fs_fdopen.c index 295a3d5902..cace0ca49d 100644 --- a/fs/vfs/fs_fdopen.c +++ b/fs/vfs/fs_fdopen.c @@ -178,36 +178,61 @@ int fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb, goto errout; } + /* Get the stream list from the TCB */ + +#ifdef CONFIG_MM_KERNEL_HEAP + slist = tcb->group->tg_streamlist; +#else + slist = &tcb->group->tg_streamlist; +#endif + /* Allocate FILE structure */ -#ifdef CONFIG_STDIO_DISABLE_BUFFERING - stream = group_zalloc(tcb->group, sizeof(FILE)); - if (stream == NULL) + if (fd >= 3) { - ret = -ENOMEM; - goto errout; + stream = group_zalloc(tcb->group, sizeof(FILE)); + if (stream == NULL) + { + ret = -ENOMEM; + goto errout; + } + + /* Add FILE structure to the stream list */ + + ret = nxsem_wait(&slist->sl_sem); + if (ret < 0) + { + group_free(tcb->group, stream); + goto errout; + } + + if (slist->sl_tail) + { + slist->sl_tail->fs_next = stream; + slist->sl_tail = stream; + } + else + { + slist->sl_head = stream; + slist->sl_tail = stream; + } + + nxsem_post(&slist->sl_sem); + + /* Initialize the semaphore the manages access to the buffer */ + + lib_sem_initialize(stream); } -#else - stream = group_malloc(tcb->group, sizeof(FILE) + - CONFIG_STDIO_BUFFER_SIZE); - if (stream == NULL) + else { - ret = -ENOMEM; - goto errout; + stream = &slist->sl_std[fd]; } - /* Zero the structure */ - - memset(stream, 0, sizeof(FILE)); - - /* Initialize the semaphore the manages access to the buffer */ - - lib_sem_initialize(stream); - +#ifndef CONFIG_STDIO_DISABLE_BUFFERING #if CONFIG_STDIO_BUFFER_SIZE > 0 /* Set up pointers */ - stream->fs_bufstart = (FAR unsigned char *)(stream + 1); + stream->fs_bufstart = stream->fs_buffer; stream->fs_bufend = &stream->fs_bufstart[CONFIG_STDIO_BUFFER_SIZE]; stream->fs_bufpos = stream->fs_bufstart; stream->fs_bufread = stream->fs_bufstart; @@ -229,34 +254,6 @@ int fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb, stream->fs_fd = fd; stream->fs_oflags = oflags; - /* Get the stream list from the TCB */ - -#ifdef CONFIG_MM_KERNEL_HEAP - slist = tcb->group->tg_streamlist; -#else - slist = &tcb->group->tg_streamlist; -#endif - - /* Add FILE structure to the stream list */ - - ret = nxsem_wait(&slist->sl_sem); - if (ret < 0) - { - goto errout_with_mem; - } - - if (slist->sl_tail) - { - slist->sl_tail->fs_next = stream; - slist->sl_tail = stream; - } - else - { - slist->sl_head = stream; - slist->sl_tail = stream; - } - - nxsem_post(&slist->sl_sem); if (filep != NULL) { *filep = stream; @@ -264,9 +261,6 @@ int fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb, return OK; -errout_with_mem: - group_free(tcb->group, stream); - errout: if (filep != NULL) { diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index 975838db76..e8ad6c4e76 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -469,6 +469,9 @@ struct file_struct FAR unsigned char *fs_bufend; /* Pointer to 1 past end of buffer */ FAR unsigned char *fs_bufpos; /* Current position in buffer */ FAR unsigned char *fs_bufread; /* Pointer to 1 past last buffered read char. */ +# if CONFIG_STDIO_BUFFER_SIZE > 0 + unsigned char fs_buffer[CONFIG_STDIO_BUFFER_SIZE]; +# endif #endif uint16_t fs_oflags; /* Open mode flags */ uint8_t fs_flags; /* Stream flags */ @@ -481,6 +484,7 @@ struct file_struct struct streamlist { sem_t sl_sem; /* For thread safety */ + struct file_struct sl_std[3]; FAR struct file_struct *sl_head; FAR struct file_struct *sl_tail; }; diff --git a/include/stdio.h b/include/stdio.h index 49f46d20fa..5608cc20df 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -78,9 +78,9 @@ /* The first three _iob entries are reserved for standard I/O */ -#define stdin (nxsched_get_streams()->sl_head) -#define stdout (nxsched_get_streams()->sl_head->fs_next) -#define stderr (nxsched_get_streams()->sl_head->fs_next->fs_next) +#define stdin (&nxsched_get_streams()->sl_std[0]) +#define stdout (&nxsched_get_streams()->sl_std[1]) +#define stderr (&nxsched_get_streams()->sl_std[2]) /* Path to the directory where temporary files can be created */ diff --git a/libs/libc/misc/lib_stream.c b/libs/libc/misc/lib_stream.c index 9a222cab53..cd07f5e481 100644 --- a/libs/libc/misc/lib_stream.c +++ b/libs/libc/misc/lib_stream.c @@ -85,6 +85,15 @@ void lib_stream_initialize(FAR struct task_group_s *group) _SEM_INIT(&list->sl_sem, 0, 1); list->sl_head = NULL; list->sl_tail = NULL; + + /* Initialize stdin, stdout and stderr stream */ + + list->sl_std[0].fs_fd = -1; + lib_sem_initialize(&list->sl_std[0]); + list->sl_std[1].fs_fd = -1; + lib_sem_initialize(&list->sl_std[1]); + list->sl_std[2].fs_fd = -1; + lib_sem_initialize(&list->sl_std[2]); } #endif /* CONFIG_FILE_STREAM */ @@ -147,6 +156,14 @@ void lib_stream_release(FAR struct task_group_s *group) group_free(group, stream); } } + + /* Destroy stdin, stdout and stderr stream */ + +#ifndef CONFIG_STDIO_DISABLE_BUFFERING + _SEM_DESTROY(&list->sl_std[0].fs_sem); + _SEM_DESTROY(&list->sl_std[1].fs_sem); + _SEM_DESTROY(&list->sl_std[2].fs_sem); +#endif } #endif /* CONFIG_FILE_STREAM */