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;
}
/* 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)
{

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_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;
};

View File

@ -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 */

View File

@ -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 */