Fix reentrancy problems for serial
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@821 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
7c18bfddad
commit
d72dd985c1
@ -115,27 +115,27 @@ extern const char g_fmtcmdoutofmemory[];
|
|||||||
|
|
||||||
/* Message handler */
|
/* Message handler */
|
||||||
|
|
||||||
extern int nsh_parse(FAR void *handle, char *cmdline);
|
extern int nsh_parse(FAR void *handle, char *cmdline);
|
||||||
|
|
||||||
/* I/O interfaces */
|
/* I/O interfaces */
|
||||||
|
|
||||||
#ifdef CONFIG_EXAMPLES_NSH_TELNET
|
extern int nsh_main(void);
|
||||||
|
extern int nsh_output(FAR void *handle, const char *fmt, ...);
|
||||||
extern int nsh_telnetmain(void);
|
extern FAR char *nsh_linebuffer(FAR void *handle);
|
||||||
extern int nsh_telnetout(FAR void *handle, const char *fmt, ...);
|
|
||||||
|
|
||||||
# define nsh_main() nsh_telnetmain()
|
|
||||||
# define nsh_output(handle, ...) nsh_telnetout(handle, __VA_ARGS__)
|
|
||||||
|
|
||||||
|
#ifndef CONFIG_EXAMPLES_NSH_TELNET /* Not yet supported on telnetd interface */
|
||||||
|
extern FAR void *nsh_clone(FAR void *handle);
|
||||||
|
extern void nsh_addref(FAR void *handle);
|
||||||
|
extern void nsh_release(FAR void *handle);
|
||||||
|
extern void *nsh_redirect(int fd);
|
||||||
|
extern void nsh_restore(void *direct);
|
||||||
#else
|
#else
|
||||||
|
# define nsh_clone(handle) (handle)
|
||||||
extern int nsh_serialmain(void);
|
# define nsh_addref(handle)
|
||||||
|
# define nsh_release(handle);
|
||||||
# define nsh_main() nsh_serialmain()
|
# define nsh_redirect(fd) (NULL);
|
||||||
# define nsh_output(handle, ...) printf(__VA_ARGS__)
|
# define nsh_restore(direct)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
extern char *nsh_linebuffer(FAR void *handle);
|
|
||||||
|
|
||||||
/* Shell command handlers */
|
/* Shell command handlers */
|
||||||
|
|
||||||
|
@ -256,6 +256,7 @@ static int nsh_execute(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
handler(handle, argc, &argv[2]);
|
handler(handle, argc, &argv[2]);
|
||||||
|
nsh_release(handle);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,16 +362,15 @@ int nsh_parse(FAR void *handle, char *cmdline)
|
|||||||
* in the "background"
|
* in the "background"
|
||||||
* argv[1]: This is string version of the handle needed to execute
|
* argv[1]: This is string version of the handle needed to execute
|
||||||
* the command (under telnetd). It is a string because
|
* the command (under telnetd). It is a string because
|
||||||
* binary values cannot be provided via char *argv[]
|
* binary values cannot be provided via char *argv[]. NOTE
|
||||||
|
* that this value is filled in later.
|
||||||
* argv[2]: The command name. This is argv[0] when the arguments
|
* argv[2]: The command name. This is argv[0] when the arguments
|
||||||
* are, finally, received by the command handler
|
* are, finally, received by the command handler
|
||||||
* argv[3]: The beginning of argument (up to NSH_MAX_ARGUMENTS)
|
* argv[3]: The beginning of argument (up to NSH_MAX_ARGUMENTS)
|
||||||
* argv[argc]: NULL terminating pointer
|
* argv[argc]: NULL terminating pointer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sprintf(strhandle, "%p\n", handle);
|
|
||||||
argv[0] = "nsh_execute";
|
argv[0] = "nsh_execute";
|
||||||
argv[1] = strhandle;
|
|
||||||
argv[2] = cmd;
|
argv[2] = cmd;
|
||||||
for (argc = 3; argc < NSH_MAX_ARGUMENTS+4; argc++)
|
for (argc = 3; argc < NSH_MAX_ARGUMENTS+4; argc++)
|
||||||
{
|
{
|
||||||
@ -400,8 +400,25 @@ int nsh_parse(FAR void *handle, char *cmdline)
|
|||||||
{
|
{
|
||||||
struct sched_param param;
|
struct sched_param param;
|
||||||
int priority;
|
int priority;
|
||||||
|
void *bkghandle;
|
||||||
|
|
||||||
/* Get the execution priority of this task */
|
/* Get a cloned copy of the handle with reference count=1.
|
||||||
|
* after the command has been processed, the nsh_release() call
|
||||||
|
* at the end of nsh_execute() will destroy the clone.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bkghandle = nsh_clone(handle);
|
||||||
|
|
||||||
|
/* Place a string copy of the cloned handle in the argument list */
|
||||||
|
|
||||||
|
sprintf(strhandle, "%p\n", bkghandle);
|
||||||
|
argv[1] = strhandle;
|
||||||
|
|
||||||
|
/* Handle redirection of output via a file descriptor */
|
||||||
|
|
||||||
|
/* (void)nsh_redirect(bkghandle); */
|
||||||
|
|
||||||
|
/* Get the execution priority of this task */
|
||||||
|
|
||||||
ret = sched_getparam(0, ¶m);
|
ret = sched_getparam(0, ¶m);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
@ -455,17 +472,43 @@ int nsh_parse(FAR void *handle, char *cmdline)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* void *save; */
|
||||||
|
|
||||||
|
/* Increment the reference count on the handle. This reference count will
|
||||||
|
* be decremented at the end of nsh_execute() and exists only for compatibility
|
||||||
|
* with the background command logic.
|
||||||
|
*/
|
||||||
|
|
||||||
|
nsh_addref(handle);
|
||||||
|
|
||||||
|
/* Place a string copy of the original handle in the argument list */
|
||||||
|
|
||||||
|
sprintf(strhandle, "%p\n", handle);
|
||||||
|
argv[1] = strhandle;
|
||||||
|
|
||||||
|
/* Handle redirection of output via a file descriptor */
|
||||||
|
/* save = nsh_redirect(fd); */
|
||||||
|
|
||||||
|
/* Then execute the command in "foreground" -- i.e., while the user waits
|
||||||
|
* for the next prompt.
|
||||||
|
*/
|
||||||
|
|
||||||
ret = nsh_execute(argc, argv);
|
ret = nsh_execute(argc, argv);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore the original output */
|
||||||
|
|
||||||
|
/* nsh_undirect(save); */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return success if the command succeeded (or at least, starting of the
|
/* Return success if the command succeeded (or at least, starting of the
|
||||||
* command task succeeded).
|
* command task succeeded).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (ret == 0)
|
return OK;
|
||||||
{
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR;
|
return ERROR;
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "nsh.h"
|
#include "nsh.h"
|
||||||
|
|
||||||
@ -54,13 +55,10 @@
|
|||||||
* Private Types
|
* Private Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
struct cmdmap_s
|
struct serial_s
|
||||||
{
|
{
|
||||||
const char *cmd; /* Name of the command */
|
int ss_refs; /* Reference counts on the intance */
|
||||||
cmd_t handler; /* Function that handles the command */
|
char ss_line[CONFIG_EXAMPLES_NSH_LINELEN];
|
||||||
ubyte minargs; /* Minimum number of arguments (including command) */
|
|
||||||
ubyte maxargs; /* Maximum number of arguments (including command) */
|
|
||||||
const char *usage; /* Usage instructions for 'help' command */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -71,8 +69,6 @@ struct cmdmap_s
|
|||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static char g_line[CONFIG_EXAMPLES_NSH_LINELEN];
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Data
|
* Public Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -81,6 +77,20 @@ static char g_line[CONFIG_EXAMPLES_NSH_LINELEN];
|
|||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nsh_allocstruct
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static inline FAR struct serial_s *nsh_allocstruct(void)
|
||||||
|
{
|
||||||
|
struct serial_s *pstate = (struct serial_s *)malloc(sizeof(struct serial_s));
|
||||||
|
if (pstate)
|
||||||
|
{
|
||||||
|
pstate->ss_refs = 1;
|
||||||
|
}
|
||||||
|
return pstate;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -89,8 +99,10 @@ static char g_line[CONFIG_EXAMPLES_NSH_LINELEN];
|
|||||||
* Name: nsh_main
|
* Name: nsh_main
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int nsh_serialmain(void)
|
int nsh_main(void)
|
||||||
{
|
{
|
||||||
|
FAR struct serial_s *pstate = nsh_allocstruct();
|
||||||
|
|
||||||
printf("NuttShell (NSH)\n");
|
printf("NuttShell (NSH)\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
@ -103,16 +115,36 @@ int nsh_serialmain(void)
|
|||||||
|
|
||||||
/* Get the next line of input */
|
/* Get the next line of input */
|
||||||
|
|
||||||
if (fgets(g_line, CONFIG_EXAMPLES_NSH_LINELEN, stdin))
|
if (fgets(pstate->ss_line, CONFIG_EXAMPLES_NSH_LINELEN, stdin))
|
||||||
{
|
{
|
||||||
/* Parse process the command */
|
/* Parse process the command */
|
||||||
|
|
||||||
(void)nsh_parse(NULL, g_line);
|
(void)nsh_parse(pstate, pstate->ss_line);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nsh_output
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Print a string to stdout.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int nsh_output(FAR void *handle, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
ret = vfprintf(stdout, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nsh_linebuffer
|
* Name: nsh_linebuffer
|
||||||
*
|
*
|
||||||
@ -121,9 +153,59 @@ int nsh_serialmain(void)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
extern char *nsh_linebuffer(FAR void *handle)
|
FAR char *nsh_linebuffer(FAR void *handle)
|
||||||
{
|
{
|
||||||
return g_line;
|
FAR struct serial_s *pstate = (FAR struct serial_s *)handle;
|
||||||
|
return pstate->ss_line;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nsh_clone
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Make an independent copy of the handle
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
FAR void *nsh_clone(FAR void *handle)
|
||||||
|
{
|
||||||
|
return nsh_allocstruct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nsh_addref
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Increment the reference count on the handle.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void nsh_addref(FAR void *handle)
|
||||||
|
{
|
||||||
|
FAR struct serial_s *pstate = (FAR struct serial_s *)handle;
|
||||||
|
pstate->ss_refs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: nsh_release
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Decrement the reference count on the handle, releasing it when the count
|
||||||
|
* decrements to zero.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void nsh_release(FAR void *handle)
|
||||||
|
{
|
||||||
|
FAR struct serial_s *pstate = (FAR struct serial_s *)handle;
|
||||||
|
if (pstate->ss_refs > 1)
|
||||||
|
{
|
||||||
|
pstate->ss_refs--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
free(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -401,7 +401,7 @@ static void *nsh_connection(void *arg)
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nsh_telnetmain
|
* Name: nsh_main
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* This is the main processing thread for telnetd. It never returns
|
* This is the main processing thread for telnetd. It never returns
|
||||||
@ -409,7 +409,7 @@ static void *nsh_connection(void *arg)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int nsh_telnetmain(void)
|
int nsh_main(void)
|
||||||
{
|
{
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
#if defined(CONFIG_EXAMPLES_NSH_DHCPC) || defined(CONFIG_EXAMPLES_NSH_NOMAC)
|
#if defined(CONFIG_EXAMPLES_NSH_DHCPC) || defined(CONFIG_EXAMPLES_NSH_NOMAC)
|
||||||
@ -492,7 +492,7 @@ int nsh_telnetmain(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: nsh_telnetout
|
* Name: nsh_output
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Print a string to the remote shell window.
|
* Print a string to the remote shell window.
|
||||||
@ -503,7 +503,7 @@ int nsh_telnetmain(void)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int nsh_telnetout(FAR void *handle, const char *fmt, ...)
|
int nsh_output(FAR void *handle, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
struct telnetd_s *pstate = (struct telnetd_s *)handle;
|
struct telnetd_s *pstate = (struct telnetd_s *)handle;
|
||||||
int nbytes = pstate->tn_sndlen;
|
int nbytes = pstate->tn_sndlen;
|
||||||
@ -558,7 +558,7 @@ int nsh_telnetout(FAR void *handle, const char *fmt, ...)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
extern char *nsh_linebuffer(FAR void *handle)
|
FAR char *nsh_linebuffer(FAR void *handle)
|
||||||
{
|
{
|
||||||
struct telnetd_s *pstate = (struct telnetd_s *)handle;
|
struct telnetd_s *pstate = (struct telnetd_s *)handle;
|
||||||
return pstate->tn_cmd;
|
return pstate->tn_cmd;
|
||||||
|
Loading…
Reference in New Issue
Block a user