0

I am using a blocking read in a thread.

When the program has to end, I sent a sigint which set a flag to end the thread; but since I'm waiting in the blocking read, the thread never stops. Is there a way to wake up the read?

mFd = open(mPort.c_str(), O_RDWR | O_NOCTTY | O_SYNC);
if(mFd == -1){
    m_logger.error("Unable to open UART. Ensure it is not in use by another application");
}

struct termios settings;

tcgetattr(mFd, &settings);
cfsetispeed(&settings, mBaudrate);

settings.c_cflag &= ~PARENB; /* no parity */
settings.c_cflag &= ~CSTOPB; /* 1 stop bit */
settings.c_cflag &= ~CSIZE;
settings.c_cflag |= CS8 | CLOCAL; /* 8 bits */
/* echo off, echo newline off, canonical mode off,
 * extended input processing off, signal chars off
 */
settings.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
settings.c_oflag = 0; /* Turn off output processing */
settings.c_cflag &=  ~CRTSCTS;
/* Read settings :
 * To understand the settings have a look at man 3 termios
 * ``Canonical and noncanonical mode`` section
 */
settings.c_cc[VMIN]   =  20; /* read doesn't block , one byte is enough to satisfy the read */
settings.c_cc[VTIME]  =  TIMEOUT_READ_BYTE_DS; /* Interbyte timer. Timeout in ds */
settings.c_cflag     |=  CREAD;

/* Flush Port, then applies attributes */
tcflush(mFd, TCIFLUSH);
if (tcsetattr(mFd, TCSANOW, &settings) < 0){
    m_logger.error("Error during the set of the attributes to the file descriptor");
    mFd= -1;
} /* apply the settings */
}

Ther read process is something like

while (EndThread==false){
    memset(buffer, 0, BUFFER_SIZE);
    bytesRead = read(mFd,buffer,BUFFER_SIZE);     //<----- I block here until I read something
    if(bytesRead < 0){
        m_logger.error("Error occurred during the reading of the serial port");
    } 
    else
    {....}

I dont know if there is a signal which can wake up the read, or if I can write on the buffer by myself in order to wake it up. I cant find any information regarding it. Can someone help me?

sawdust
  • 16,103
  • 3
  • 40
  • 50
  • 1
    There are many ways to do this. Open a second file descriptor to a named pipe. Use `poll()` to read simultanously from both file descriptor. When something's read from the pipe terminate the program. And instead of sending a signal open the the pipe and write one byte to it, that's it. Or, alternatively, with signals on Linux, you can set up and create a single file descriptor and, basically, use the same `poll()`-based approach. Both of these requite a bit of work, and are just too long to write up in a short answer on Stackoverflow, but you can find more info in Google. – Sam Varshavchik May 24 '20 at 16:23
  • so you are saying that I should write into my File descriptor once i receive the signal and the poll will unlock. But why cant I do the same with the read I am using? should I rewrite all the code to use an analogue function? Or maybe I missunderstood what you are trying to explain to me. (sorry but I could have some lack of knowledge in this type of communication) – Seriousl Lancerl May 24 '20 at 16:58
  • No, you misunderstood what I was trying to explain to you. Sounds like you are not familiar with the `poll()` system call, and what it does. I can't explain anything more than what I already did, you need to learn how `poll()` works, and what it does. You also need to learn Linux signal file descriptors, and how to use them, the `signalfd` manual page. – Sam Varshavchik May 24 '20 at 19:43
  • 1
    *"I sent a `sigint` ... but since I'm waiting in the blocking read, the thread never stops."* -- The man page for **read(2)** clearly indicates that this syscall can be "interrupted by a signal before any data was read" and return with errno= EINTR. So maybe your program's signal setup and handling for this thread is suspect, all of which you neglect to show. *"I cant find any information regarding it."* -- See https://stackoverflow.com/questions/11679568/signal-handling-with-multiple-threads-in-linux BTW your program does not open or read a *"UART"*, but a serial terminal. – sawdust May 25 '20 at 00:51
  • @sawdust that is exactly what I read too about the signal which should wake up the blocked read, this is the main reason I asked this question, because I wanted to understand if there is a way to send the signal to the read(and so the thread).I thought all the thread received the signal but from what I read in your link that is not completely true. I tried to put the read in the main thread just to do some test but it still doesn't work. I subscribe to the signal with 'signal(SIGINT, StopApplication);' – Seriousl Lancerl May 26 '20 at 22:24
  • Vote to close. *"I tried ... but it still doesn't work"* -- Summary lacks details (e.g. which threads library), is not a replacement for the [required minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example), and insufficient for analysis. *"I subscribe to the signal with 'signal(...)"* -- Apparently you haven't read the Linux **man** page for **signal(2)**: "The behavior of **signal()** varies across UNIX versions, and has also varied historically across different versions of Linux. **Avoid its use**" (not my emphasis). – sawdust May 27 '20 at 01:58

0 Answers0