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 <xiaoxiang@xiaomi.com>
This commit is contained in:
Xiang Xiao 2020-11-09 13:32:59 +08:00 committed by David Sidrane
parent 1dad55d4be
commit 84b90e00f0
4 changed files with 69 additions and 54 deletions

View File

@ -178,36 +178,61 @@ int fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb,
goto errout; 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 */ /* Allocate FILE structure */
#ifdef CONFIG_STDIO_DISABLE_BUFFERING if (fd >= 3)
stream = group_zalloc(tcb->group, sizeof(FILE));
if (stream == NULL)
{ {
ret = -ENOMEM; stream = group_zalloc(tcb->group, sizeof(FILE));
goto errout; 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 else
stream = group_malloc(tcb->group, sizeof(FILE) +
CONFIG_STDIO_BUFFER_SIZE);
if (stream == NULL)
{ {
ret = -ENOMEM; stream = &slist->sl_std[fd];
goto errout;
} }
/* Zero the structure */ #ifndef CONFIG_STDIO_DISABLE_BUFFERING
memset(stream, 0, sizeof(FILE));
/* Initialize the semaphore the manages access to the buffer */
lib_sem_initialize(stream);
#if CONFIG_STDIO_BUFFER_SIZE > 0 #if CONFIG_STDIO_BUFFER_SIZE > 0
/* Set up pointers */ /* 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_bufend = &stream->fs_bufstart[CONFIG_STDIO_BUFFER_SIZE];
stream->fs_bufpos = stream->fs_bufstart; stream->fs_bufpos = stream->fs_bufstart;
stream->fs_bufread = 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_fd = fd;
stream->fs_oflags = oflags; 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) if (filep != NULL)
{ {
*filep = stream; *filep = stream;
@ -264,9 +261,6 @@ int fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb,
return OK; return OK;
errout_with_mem:
group_free(tcb->group, stream);
errout: errout:
if (filep != NULL) if (filep != NULL)
{ {

View File

@ -469,6 +469,9 @@ struct file_struct
FAR unsigned char *fs_bufend; /* Pointer to 1 past end of buffer */ 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_bufpos; /* Current position in buffer */
FAR unsigned char *fs_bufread; /* Pointer to 1 past last buffered read char. */ 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 #endif
uint16_t fs_oflags; /* Open mode flags */ uint16_t fs_oflags; /* Open mode flags */
uint8_t fs_flags; /* Stream flags */ uint8_t fs_flags; /* Stream flags */
@ -481,6 +484,7 @@ struct file_struct
struct streamlist struct streamlist
{ {
sem_t sl_sem; /* For thread safety */ sem_t sl_sem; /* For thread safety */
struct file_struct sl_std[3];
FAR struct file_struct *sl_head; FAR struct file_struct *sl_head;
FAR struct file_struct *sl_tail; FAR struct file_struct *sl_tail;
}; };

View File

@ -78,9 +78,9 @@
/* The first three _iob entries are reserved for standard I/O */ /* The first three _iob entries are reserved for standard I/O */
#define stdin (nxsched_get_streams()->sl_head) #define stdin (&nxsched_get_streams()->sl_std[0])
#define stdout (nxsched_get_streams()->sl_head->fs_next) #define stdout (&nxsched_get_streams()->sl_std[1])
#define stderr (nxsched_get_streams()->sl_head->fs_next->fs_next) #define stderr (&nxsched_get_streams()->sl_std[2])
/* Path to the directory where temporary files can be created */ /* Path to the directory where temporary files can be created */

View File

@ -85,6 +85,15 @@ void lib_stream_initialize(FAR struct task_group_s *group)
_SEM_INIT(&list->sl_sem, 0, 1); _SEM_INIT(&list->sl_sem, 0, 1);
list->sl_head = NULL; list->sl_head = NULL;
list->sl_tail = 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 */ #endif /* CONFIG_FILE_STREAM */
@ -147,6 +156,14 @@ void lib_stream_release(FAR struct task_group_s *group)
group_free(group, stream); 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 */ #endif /* CONFIG_FILE_STREAM */