Squashed commit of the following:

drivers/serial:  Add Ctrl-C/Ctrl-X support.  This is an initial working implementation that still requires that several details be resolved.

    sched/task/task_start.c: Add default signal action to SIGKILL.
This commit is contained in:
ligd
2018-08-26 08:49:08 -06:00
committed by Gregory Nutt
parent 729a65f3ab
commit 11f8dc735c
9 changed files with 286 additions and 23 deletions
+2 -10
View File
@@ -1,4 +1,4 @@
NuttX TODO List (Last updated June 21, 2018) NuttX TODO List (Last updated August 26, 2018)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with This file summarizes known NuttX bugs, limitations, inconsistencies with
@@ -21,7 +21,7 @@ nuttx/:
(5) Binary loaders (binfmt/) (5) Binary loaders (binfmt/)
(16) Network (net/, drivers/net) (16) Network (net/, drivers/net)
(4) USB (drivers/usbdev, drivers/usbhost) (4) USB (drivers/usbdev, drivers/usbhost)
(2) Other drivers (drivers/) (1) Other drivers (drivers/)
(12) Libraries (libc/, libm/) (12) Libraries (libc/, libm/)
(10) File system/Generic drivers (fs/, drivers/) (10) File system/Generic drivers (fs/, drivers/)
(10) Graphics Subsystem (graphics/) (10) Graphics Subsystem (graphics/)
@@ -2138,14 +2138,6 @@ o Other drivers (drivers/)
debug if you could see all of the SYSLOG output up to the debug if you could see all of the SYSLOG output up to the
time of the crash. But not essential. time of the crash. But not essential.
Title: ADD SUPPORT FOR CONTROL-C
Description: Add support for control-C interrupts and perhaps other
interrupts generated from a keyboard.
Status: Open
Priority: Low. This would make working with tasks at the NSH terminal
more like working with processes via a Bash shell. That is
a feature enhancement.
o Linux/Cywgin simulation (arch/sim) o Linux/Cywgin simulation (arch/sim)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+12
View File
@@ -19,6 +19,18 @@ config SERIAL_CONSOLE
bool bool
default n default n
config SERIAL_SIGKILL_CHAR
int "Serial parse SIGKILL characters"
default 3 if SERIAL_CONSOLE
default 4 if !SERIAL_CONSOLE
depends on SIG_SIGKILL
---help---
Use ASCII 3 (Ctrl-c) or 4 (ctrl-d) inputs to determine whether to
send a SIGKILL event. Other charcters may also be selected.
REVISIT: Traditionally Ctrl-C would generate SIGINT. Ctrl-D is the
End-of-File character that should close the stream.
menuconfig 16550_UART menuconfig 16550_UART
bool "16550 UART Chip support" bool "16550 UART Chip support"
default n default n
+47 -9
View File
@@ -1,7 +1,7 @@
/************************************************************************************ /************************************************************************************
* drivers/serial/serial.c * drivers/serial/serial.c
* *
* Copyright (C) 2007-2009, 2011-2013, 2016-2017 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2011-2013, 2016-2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -703,14 +703,7 @@ static int uart_close(FAR struct file *filep)
* a thread currently blocking on any of them. * a thread currently blocking on any of them.
*/ */
nxsem_reset(&dev->xmitsem, 0); uart_reset_sem(dev);
nxsem_reset(&dev->recvsem, 0);
nxsem_reset(&dev->xmit.sem, 1);
nxsem_reset(&dev->recv.sem, 1);
#ifndef CONFIG_DISABLE_POLL
nxsem_reset(&dev->pollsem, 1);
#endif
uart_givesem(&dev->closesem); uart_givesem(&dev->closesem);
return OK; return OK;
} }
@@ -1376,6 +1369,25 @@ static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
} }
break; break;
#endif #endif
#ifdef CONFIG_SERIAL_SIGKILL_CHAR
case TIOCSCTTY:
{
/* REVISIT: This only applies to console devices (TTYs). In
* reality, this feature should be controlled by TERMIOS ISIG
* c_lflag setting.
*/
if (dev->isconsole)
{
/* Save the PID of the recipient of the SIGKILL signal. */
dev->pid = (pid_t)arg;
DEBUGASSERT((unsigned long)dev->pid = arg);
}
}
break;
#endif
} }
} }
@@ -1584,6 +1596,12 @@ errout:
int uart_register(FAR const char *path, FAR uart_dev_t *dev) int uart_register(FAR const char *path, FAR uart_dev_t *dev)
{ {
#ifdef CONFIG_SERIAL_SIGKILL_CHAR
/* Initialize of the task that will receive SIGKILL signals. */
dev->pid = -1;
#endif
/* Initialize semaphores */ /* Initialize semaphores */
nxsem_init(&dev->xmit.sem, 0, 1); nxsem_init(&dev->xmit.sem, 0, 1);
@@ -1728,3 +1746,23 @@ void uart_connected(FAR uart_dev_t *dev, bool connected)
leave_critical_section(flags); leave_critical_section(flags);
} }
#endif #endif
/************************************************************************************
* Name: uart_reset_sem
*
* Description:
* This function is called when need reset uart semphore, this may used in kill one
* process, but this process was reading/writing with the semphore.
*
************************************************************************************/
void uart_reset_sem(FAR uart_dev_t *dev)
{
nxsem_reset(&dev->xmitsem, 0);
nxsem_reset(&dev->recvsem, 0);
nxsem_reset(&dev->xmit.sem, 1);
nxsem_reset(&dev->recv.sem, 1);
#ifndef CONFIG_DISABLE_POLL
nxsem_reset(&dev->pollsem, 1);
#endif
}
+82 -1
View File
@@ -1,7 +1,7 @@
/************************************************************************************ /************************************************************************************
* drivers/serial/serial_dma.c * drivers/serial/serial_dma.c
* *
* Copyright (C) 2015 Gregory Nutt. All rights reserved. * Copyright (C) 2015, 2018 Gregory Nutt. All rights reserved.
* Author: Max Neklyudov <macscomp@gmail.com> * Author: Max Neklyudov <macscomp@gmail.com>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -48,6 +48,67 @@
#ifdef CONFIG_SERIAL_DMA #ifdef CONFIG_SERIAL_DMA
/************************************************************************************
* Private Functions
************************************************************************************/
/************************************************************************************
* Name: uart_check_sigkill
*
* Description:
* Check if the SIGKILL character is in the contiguous Rx DMA buffer region.
*
************************************************************************************/
#ifdef CONFIG_SIG_SIGKILL
static bool uart_check_sigkill(const char *buf, size_t size)
{
size_t i;
for (i = 0; i < size; i++)
{
if (buf[i] == CONFIG_SERIAL_SIGKILL_CHAR)
{
return true;
}
}
return false;
}
#endif
/************************************************************************************
* Name: uart_recvchars_sigkill
*
* Description:
* Check if the SIGKILL character is anywhere in the newly received DMA buffer.
*
* REVISIT: We must also remove the SIGKILL character from the Rx buffer. It
* should not be read as normal data by the caller.
*
************************************************************************************/
#ifdef CONFIG_SIG_SIGKILL
static bool uart_recvchars_sigkill(FAR uart_dev_t *dev)
{
FAR struct uart_dmaxfer_s *xfer = &dev->dmarx;
if (xfer->nbytes <= xfer->length)
{
return uart_check_sigkill(xfer->buffer, xfer->nbytes);
}
else
{
if (uart_check_sigkill(xfer->buffer, xfer->length))
{
return true;
}
return uart_check_sigkill(xfer->nbuffer, xfer->nbytes - xfer->length);
}
}
#endif
/************************************************************************************ /************************************************************************************
* Public Functions * Public Functions
************************************************************************************/ ************************************************************************************/
@@ -250,6 +311,16 @@ void uart_recvchars_done(FAR uart_dev_t *dev)
FAR struct uart_dmaxfer_s *xfer = &dev->dmarx; FAR struct uart_dmaxfer_s *xfer = &dev->dmarx;
FAR struct uart_buffer_s *rxbuf = &dev->recv; FAR struct uart_buffer_s *rxbuf = &dev->recv;
size_t nbytes = xfer->nbytes; size_t nbytes = xfer->nbytes;
#ifdef CONFIG_SIG_SIGKILL
bool needkill = false;
/* Check if the SIGKILL character is anywhere in the newly received DMA buffer. */
if (dev->pid >= 0 && uart_recvchars_sigkill(dev))
{
needkill = true;
}
#endif
/* Move head for nbytes. */ /* Move head for nbytes. */
@@ -265,6 +336,16 @@ void uart_recvchars_done(FAR uart_dev_t *dev)
{ {
uart_datareceived(dev); uart_datareceived(dev);
} }
#ifdef CONFIG_SIG_SIGKILL
/* Send the SIGKILL signal if needed */
if (needkill)
{
kill(dev->pid, SIGKILL);
uart_reset_sem(dev);
}
#endif
} }
#endif /* CONFIG_SERIAL_DMA */ #endif /* CONFIG_SERIAL_DMA */
+30 -1
View File
@@ -1,7 +1,7 @@
/************************************************************************************ /************************************************************************************
* drivers/serial/serial_io.c * drivers/serial/serial_io.c
* *
* Copyright (C) 2007-2009, 2011, 2015 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2011, 2015, 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -122,6 +122,9 @@ void uart_recvchars(FAR uart_dev_t *dev)
FAR struct uart_buffer_s *rxbuf = &dev->recv; FAR struct uart_buffer_s *rxbuf = &dev->recv;
#ifdef CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS #ifdef CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS
unsigned int watermark; unsigned int watermark;
#endif
#ifdef CONFIG_SIG_SIGKILL
bool needkill = false;
#endif #endif
unsigned int status; unsigned int status;
int nexthead = rxbuf->head + 1; int nexthead = rxbuf->head + 1;
@@ -194,8 +197,24 @@ void uart_recvchars(FAR uart_dev_t *dev)
#endif #endif
#endif #endif
/* Get this next character from the hardware */
ch = uart_receive(dev, &status); ch = uart_receive(dev, &status);
#ifdef CONFIG_SIG_SIGKILL
/* Is this the special character that will generate the SIGKILL signal? */
if (dev->pid >= 0 && ch == CONFIG_SERIAL_SIGKILL_CHAR)
{
/* Yes.. not the the kill is needed and do not put the character into
* the Rx buffer. It should not be read as normal data.
*/
needkill = true;
}
else
#endif
/* If the RX buffer becomes full, then the serial data is discarded. This is /* If the RX buffer becomes full, then the serial data is discarded. This is
* necessary because on most serial hardware, you must read the data in order * necessary because on most serial hardware, you must read the data in order
* to clear the RX interrupt. An option on some hardware might be to simply * to clear the RX interrupt. An option on some hardware might be to simply
@@ -229,4 +248,14 @@ void uart_recvchars(FAR uart_dev_t *dev)
{ {
uart_datareceived(dev); uart_datareceived(dev);
} }
#ifdef CONFIG_SIG_SIGKILL
/* Send the SIGKILL signal if needed */
if (needkill)
{
kill(dev->pid, SIGKILL);
uart_reset_sem(dev);
}
#endif
} }
+16 -1
View File
@@ -1,7 +1,7 @@
/************************************************************************************ /************************************************************************************
* include/nuttx/serial/serial.h * include/nuttx/serial/serial.h
* *
* Copyright (C) 2007-2008, 2012-2015 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2008, 2012-2015, 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -288,6 +288,10 @@ struct uart_dev_s
tcflag_t tc_lflag; /* Local modes */ tcflag_t tc_lflag; /* Local modes */
#endif #endif
#ifdef CONFIG_SERIAL_SIGKILL_CHAR
pid_t pid; /* Thread PID to receive SIGKILL signals (-1 if none) */
#endif
/* Semaphores */ /* Semaphores */
sem_t closesem; /* Locks out new open while close is in progress */ sem_t closesem; /* Locks out new open while close is in progress */
@@ -481,6 +485,17 @@ void uart_recvchars_dma(FAR uart_dev_t *dev);
void uart_recvchars_done(FAR uart_dev_t *dev); void uart_recvchars_done(FAR uart_dev_t *dev);
#endif #endif
/************************************************************************************
* Name: uart_reset_sem
*
* Description:
* This function is called when need reset uart semphore, this may used in kill one
* process, but this process was reading/writing with the semphore.
*
************************************************************************************/
void uart_reset_sem(FAR uart_dev_t *dev);
#undef EXTERN #undef EXTERN
#if defined(__cplusplus) #if defined(__cplusplus)
} }
+9 -1
View File
@@ -1,7 +1,7 @@
/******************************************************************************** /********************************************************************************
* include/signal.h * include/signal.h
* *
* Copyright (C) 2007-2009, 2011, 2013-2017 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2011, 2013-2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -169,6 +169,14 @@
# endif # endif
#endif #endif
#ifdef CONFIG_SIG_SIGKILL
# ifndef CONFIG_SIG_KILL
# define SIGKILL 9 /* Sent when ctrl-c event (vs. standard SIGINT) */
# else
# define SIGKILL CONFIG_SIG_KILL
# endif
#endif
/* The following are non-standard signal definitions */ /* The following are non-standard signal definitions */
#ifndef CONFIG_DISABLE_PTHREAD #ifndef CONFIG_DISABLE_PTHREAD
+19
View File
@@ -1184,6 +1184,15 @@ config SIG_EVTHREAD
different mechanism would need to be development to support this different mechanism would need to be development to support this
feature on the PROTECTED or KERNEL build. feature on the PROTECTED or KERNEL build.
config SIG_SIGKILL
bool "Support SIGKILL"
default n
depends on !DISABLE_SIGNALS
---help---
Whether support Ctrl-c/x event, or kill -9 cmd.
NOTE: SIGINT is normally sent by Ctrl-C in other systems.
menu "Signal Numbers" menu "Signal Numbers"
depends on !DISABLE_SIGNALS depends on !DISABLE_SIGNALS
@@ -1223,6 +1232,16 @@ config SIG_POLL
The SIGPOLL signal is sent to a process when an asynchronous I/O The SIGPOLL signal is sent to a process when an asynchronous I/O
event occurs (meaning it has been polled). Default: 5 event occurs (meaning it has been polled). Default: 5
config SIG_KILL
int "SIGKILL"
default 9
depends on SIG_SIGKILL
---help---
The SIGKILL signal is sent to a process when Ctrl-c/x event,
or cmd kill -9 xx happened.
NOTE: SIGINT is normally sent by Ctrl-C in other systems.
config SIG_SIGCONDTIMEDOUT config SIG_SIGCONDTIMEDOUT
int "SIGCONDTIMEDOUT" int "SIGCONDTIMEDOUT"
default 16 default 16
+69
View File
@@ -42,22 +42,85 @@
#include <stdlib.h> #include <stdlib.h>
#include <sched.h> #include <sched.h>
#include <debug.h> #include <debug.h>
#include <string.h>
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/sched.h> #include <nuttx/sched.h>
#include "group/group.h"
#include "sched/sched.h" #include "sched/sched.h"
#include "task/task.h" #include "task/task.h"
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* This is an artificial limit to detect error conditions where an argv[] /* This is an artificial limit to detect error conditions where an argv[]
* list is not properly terminated. * list is not properly terminated.
*/ */
#define MAX_START_ARGS 256 #define MAX_START_ARGS 256
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: task_sigkill_action
*
* Description:
* This is the default action for the SIGKILL signal.
*
* REVISIT: I think there is an issue here in the PROTECTED and KERNEL
* build modes. In those cases, the signal handler will go through a
* trampoline that drops to user mode for execution of the signal handler.
* In the PROTECTED mode, this will forward the call to here in user mode
* which will result in a crash. The behavior in KERNEL mode in
* indeterminate.
*
* Input Parameters:
* Standard signal handler parameters
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_SIG_SIGKILL
static void task_sigkill_action(int signo, siginfo_t *siginfo, void *arg)
{
#ifdef HAVE_GROUP_MEMBERS
FAR struct task_tcb_s *tcb = (FAR struct task_tcb_s *)this_task();
group_killchildren(tcb);
#endif
exit(EXIT_FAILURE);
}
/****************************************************************************
* Name: task_setup_sigkill
*
* Description:
* Setup the default action for the SIGKILL signal
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static inline void task_setup_sigkill(void)
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = task_sigkill_action;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGKILL, &sa, NULL);
}
#endif
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/
@@ -86,6 +149,12 @@ void task_start(void)
DEBUGASSERT((tcb->cmn.flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD); DEBUGASSERT((tcb->cmn.flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD);
/* Set up default signal actions */
#ifdef CONFIG_SIG_SIGKILL
task_setup_sigkill();
#endif
/* Execute the start hook if one has been registered */ /* Execute the start hook if one has been registered */
#ifdef CONFIG_SCHED_STARTHOOK #ifdef CONFIG_SCHED_STARTHOOK