summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-08-14 23:37:12 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-08-14 23:37:12 +0000
commit24738c1122691d74a8a3b7713c2878d5ed32486c (patch)
tree95474c328e4af9e7a046267ac03eaa3eeceb144f
parent3169482b6c251e6c532b96c7af5ce2b181660706 (diff)
downloadpx4-nuttx-24738c1122691d74a8a3b7713c2878d5ed32486c.tar.gz
px4-nuttx-24738c1122691d74a8a3b7713c2878d5ed32486c.tar.bz2
px4-nuttx-24738c1122691d74a8a3b7713c2878d5ed32486c.zip
Fix reentrancy problems for serial
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@821 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/examples/nsh/nsh.h30
-rw-r--r--nuttx/examples/nsh/nsh_main.c59
-rw-r--r--nuttx/examples/nsh/nsh_serial.c108
-rw-r--r--nuttx/examples/nsh/nsh_telnetd.c10
4 files changed, 166 insertions, 41 deletions
diff --git a/nuttx/examples/nsh/nsh.h b/nuttx/examples/nsh/nsh.h
index 0cc47274a..ff6df6b24 100644
--- a/nuttx/examples/nsh/nsh.h
+++ b/nuttx/examples/nsh/nsh.h
@@ -115,27 +115,27 @@ extern const char g_fmtcmdoutofmemory[];
/* Message handler */
-extern int nsh_parse(FAR void *handle, char *cmdline);
+extern int nsh_parse(FAR void *handle, char *cmdline);
/* I/O interfaces */
-#ifdef CONFIG_EXAMPLES_NSH_TELNET
-
-extern int nsh_telnetmain(void);
-extern int nsh_telnetout(FAR void *handle, const char *fmt, ...);
-
-# define nsh_main() nsh_telnetmain()
-# define nsh_output(handle, ...) nsh_telnetout(handle, __VA_ARGS__)
+extern int nsh_main(void);
+extern int nsh_output(FAR void *handle, const char *fmt, ...);
+extern FAR char *nsh_linebuffer(FAR void *handle);
+#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
-
-extern int nsh_serialmain(void);
-
-# define nsh_main() nsh_serialmain()
-# define nsh_output(handle, ...) printf(__VA_ARGS__)
-
+# define nsh_clone(handle) (handle)
+# define nsh_addref(handle)
+# define nsh_release(handle);
+# define nsh_redirect(fd) (NULL);
+# define nsh_restore(direct)
#endif
-extern char *nsh_linebuffer(FAR void *handle);
/* Shell command handlers */
diff --git a/nuttx/examples/nsh/nsh_main.c b/nuttx/examples/nsh/nsh_main.c
index 785062bc5..cf20141cb 100644
--- a/nuttx/examples/nsh/nsh_main.c
+++ b/nuttx/examples/nsh/nsh_main.c
@@ -256,6 +256,7 @@ static int nsh_execute(int argc, char *argv[])
}
handler(handle, argc, &argv[2]);
+ nsh_release(handle);
return OK;
}
@@ -361,16 +362,15 @@ int nsh_parse(FAR void *handle, char *cmdline)
* in the "background"
* argv[1]: This is string version of the handle needed to execute
* 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
* are, finally, received by the command handler
* argv[3]: The beginning of argument (up to NSH_MAX_ARGUMENTS)
* argv[argc]: NULL terminating pointer
*/
- sprintf(strhandle, "%p\n", handle);
argv[0] = "nsh_execute";
- argv[1] = strhandle;
argv[2] = cmd;
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;
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, &param);
if (ret != 0)
@@ -455,17 +472,43 @@ int nsh_parse(FAR void *handle, char *cmdline)
}
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);
+ if (ret < 0)
+ {
+ return ERROR;
+ }
+
+ /* Restore the original output */
+
+ /* nsh_undirect(save); */
}
/* Return success if the command succeeded (or at least, starting of the
* command task succeeded).
*/
- if (ret == 0)
- {
- return OK;
- }
+ return OK;
}
return ERROR;
diff --git a/nuttx/examples/nsh/nsh_serial.c b/nuttx/examples/nsh/nsh_serial.c
index 5052109d2..fee653266 100644
--- a/nuttx/examples/nsh/nsh_serial.c
+++ b/nuttx/examples/nsh/nsh_serial.c
@@ -43,6 +43,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdarg.h>
#include "nsh.h"
@@ -54,13 +55,10 @@
* Private Types
****************************************************************************/
-struct cmdmap_s
+struct serial_s
{
- const char *cmd; /* Name of the command */
- cmd_t handler; /* Function that handles the command */
- ubyte minargs; /* Minimum number of arguments (including command) */
- ubyte maxargs; /* Maximum number of arguments (including command) */
- const char *usage; /* Usage instructions for 'help' command */
+ int ss_refs; /* Reference counts on the intance */
+ char ss_line[CONFIG_EXAMPLES_NSH_LINELEN];
};
/****************************************************************************
@@ -71,8 +69,6 @@ struct cmdmap_s
* Private Data
****************************************************************************/
-static char g_line[CONFIG_EXAMPLES_NSH_LINELEN];
-
/****************************************************************************
* Public Data
****************************************************************************/
@@ -82,6 +78,20 @@ static char g_line[CONFIG_EXAMPLES_NSH_LINELEN];
****************************************************************************/
/****************************************************************************
+ * 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
****************************************************************************/
@@ -89,8 +99,10 @@ static char g_line[CONFIG_EXAMPLES_NSH_LINELEN];
* Name: nsh_main
****************************************************************************/
-int nsh_serialmain(void)
+int nsh_main(void)
{
+ FAR struct serial_s *pstate = nsh_allocstruct();
+
printf("NuttShell (NSH)\n");
fflush(stdout);
@@ -103,17 +115,37 @@ int nsh_serialmain(void)
/* 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 */
- (void)nsh_parse(NULL, g_line);
+ (void)nsh_parse(pstate, pstate->ss_line);
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
*
* Description:
@@ -121,9 +153,59 @@ int nsh_serialmain(void)
*
****************************************************************************/
-extern char *nsh_linebuffer(FAR void *handle)
+FAR char *nsh_linebuffer(FAR void *handle)
+{
+ 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 g_line;
+ 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);
+ }
}
/****************************************************************************
diff --git a/nuttx/examples/nsh/nsh_telnetd.c b/nuttx/examples/nsh/nsh_telnetd.c
index 0dbf6b18b..3f1c1374d 100644
--- a/nuttx/examples/nsh/nsh_telnetd.c
+++ b/nuttx/examples/nsh/nsh_telnetd.c
@@ -401,7 +401,7 @@ static void *nsh_connection(void *arg)
****************************************************************************/
/****************************************************************************
- * Name: nsh_telnetmain
+ * Name: nsh_main
*
* Description:
* 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;
#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:
* 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;
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;
return pstate->tn_cmd;