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
+12
View File
@@ -19,6 +19,18 @@ config SERIAL_CONSOLE
bool
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
bool "16550 UART Chip support"
default n
+47 -9
View File
@@ -1,7 +1,7 @@
/************************************************************************************
* 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>
*
* 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.
*/
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
uart_reset_sem(dev);
uart_givesem(&dev->closesem);
return OK;
}
@@ -1376,6 +1369,25 @@ static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
break;
#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)
{
#ifdef CONFIG_SERIAL_SIGKILL_CHAR
/* Initialize of the task that will receive SIGKILL signals. */
dev->pid = -1;
#endif
/* Initialize semaphores */
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);
}
#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
*
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2015, 2018 Gregory Nutt. All rights reserved.
* Author: Max Neklyudov <macscomp@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
@@ -48,6 +48,67 @@
#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
************************************************************************************/
@@ -250,6 +311,16 @@ void uart_recvchars_done(FAR uart_dev_t *dev)
FAR struct uart_dmaxfer_s *xfer = &dev->dmarx;
FAR struct uart_buffer_s *rxbuf = &dev->recv;
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. */
@@ -265,6 +336,16 @@ void uart_recvchars_done(FAR uart_dev_t *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 */
+30 -1
View File
@@ -1,7 +1,7 @@
/************************************************************************************
* 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>
*
* 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;
#ifdef CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS
unsigned int watermark;
#endif
#ifdef CONFIG_SIG_SIGKILL
bool needkill = false;
#endif
unsigned int status;
int nexthead = rxbuf->head + 1;
@@ -194,8 +197,24 @@ void uart_recvchars(FAR uart_dev_t *dev)
#endif
#endif
/* Get this next character from the hardware */
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
* 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
@@ -229,4 +248,14 @@ void uart_recvchars(FAR uart_dev_t *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
}