In my user space Linux application, I have a thread which communicated to the main process through a pipe. Below is the code
static void _notify_main(int cond)
{
int r;
int tmp = cond;
r = write( _nfy_fd, &tmp, sizeof(tmp) );
ERROR( "write failed: %d. %s\n", r, strerror(r) );
}
Pretty straight forward. It's been working fine for quite a while now. But recently, the write call will fail with "interrupted system call" error after the programme went under some stress test.
Strangely, the stuff actually went through the pipe no problem. Of course I'd still like to go to the bottom of the error message and get rid of it.
Thanks,
The write(2) man page mentions:
Conforming to
SVr4, 4.3BSD, POSIX.1-2001.
Under SVr4 a write may be interrupted and return EINTR at any point, not just before any data is written.
I guess you were just lucky that it didn't occur so far.
If you google just for the "interrupted system call", you will find this thread which tells you to use siginterrupt() to auto-restart the write call.
From http://www.gnu.org/
A signal can arrive and be handled while an I/O primitive such as open
or read is waiting for an I/O device. If the signal handler returns,
the system faces the question: what should happen next?
POSIX specifies one approach: make the primitive fail right away. The
error code for this kind of failure is EINTR. This is flexible, but
usually inconvenient. Typically, POSIX applications that use signal
handlers must check for EINTR after each library function that can
return it, in order to try the call again. Often programmers forget to
check, which is a common source of error.
So you can handle the EINTR error, there is another choice by the way, You can use sigaction to establish a signal handler specifying how that handler should behave. Using the SA_RESTART flag, return from that handler will resume a primitive; otherwise, return from that handler will cause EINTR.
see interrupted primitives
Related
Reading Qt signal & slots documentation, it seems that the only reason for a new style connection to fail is:
"If there is already a duplicate (exact same signal to the exact same slot on the same objects), the connection will fail and connect will return false"
Which means that connection was already successful the first time and does not allow multi-connections when using Qt::UniqueConnection.
Does this means that Qt-5 style connection will always success? Are there any other reasons for failure?
The new-style connect can still fail at runtime for a variety of reasons:
Either sender or receiver is a null pointer. Obviously this requires a check that can only happen at runtime.
The PMF you specified for a signal is not actually a signal. Lacking proper C++ reflection capabilities, all you can do at compile time is checking that the signal is a non-static member function of the sender's class.
However, that's not enough to make it a signal: it also needs to be in a signals: section in your class definition. When moc sees your class definition, it will generate some metadata containing the information that that function is indeed a signal. So, at runtime, the pointer passed to connect is looked up in a table, and connect itself will fail if the pointer is not found (because you did not pass a signal).
The check on the previous point actually requires a comparison between pointers to member functions. It's a particularly tricky one, because it will typically involve different TUs:
one is the TU containing moc-generated data (typically a moc_class.cpp file). In this TU there's the aforementioned table containing, amongst other things, pointers to the signals (which are just ordinary member functions).
is the TU where you actually invoke connect(sender, &Sender::signal, ...), which generates the pointer that gets looked up in the table.
Now, the two TUs may be in the same application, or perhaps one is in a library and the other in your application, or maybe in two libraries, etc; your platform's ABI starts to get into play.
In theory, the pointers stored when doing 1. are identical to the pointers generated when doing 2.; in practice, we've found cases where this does not happen (cf. this bug report that I reported some time ago, where older versions of GNU ld on ARM generated code that failed the comparison).
For Qt this meant disabling certain optimizations and/or passing some extra flags to the places where we know this to happen and break user software. For instance, as of Qt 5.9, there is no support for -Bsymbolic* flags on GCC on anything but x86 and x86-64.
Of course, this does not mean we've found and fixed all the possible places. New compilers and more aggressive optimizations might trigger this bug again in the future, making connect return false, even when everything is supposed to work.
Yes it can fail if either sender or receiver are not valid objects (nullptr for example)
Example
QObject* obj1 = new QObject();
QObject* obj2 = new QObject();
// Will succeed
connect(obj1, &QObject::destroyed, obj2, &QObject::deleteLater);
delete obj1;
obj1 = nullptr;
// Will fail even if it compiles
connect(obj1, &QObject::destroyed, obj2, &QObject::deleteLater);
Do not try to register pointer type. I've used the macro
#define QT_REG_TYPE(T) qRegisterMetaType<T>(#T)
with pointer type CMyWidget*, that was the problem. Using the type directly worked.
No it's not always successful. The docs give an example here where connect would return false because the signal should not contain variable names.
// WRONG
QObject::connect(scrollBar, SIGNAL(valueChanged(int value)),
label, SLOT(setNum(int value)));
I am using Pin for dynamic analysis.
In my dynamic analysis task on 64-bit x86 binary code, I would like to resume the execution at arbitrary program positions (e.g., the second instruction of current executed function) after I fix certain memory access error inside the signal handling callbacks.
It would be something like this:
BOOL catchSignalSEGV(THREADID tid, INT32 sig, CONTEXT *ctx, BOOL hasHandler, const EXCEPTION_INFO *pExceptInfo, VOID *v)
{
// I will first fix the memory access error according to certain rules.
fix();
// then I would like to resume the execution at an arbitrary position, say, at the beginning of current monitored function
set_reg(rip, 0x123456); // set the rip register
PIN_ExecuteAt(ctx); // resume the execution
return false;
}
However, I got this exception: E: PIN_ExecuteAt() cannot be called from a callback.
I know I can resume the execution at "current instruction" by return false at the end of the signal handling function, but basically can I resume at arbitrary positions?
Am I clear? Thank you for your help!
The documentation is clear on this:
A tool can call this API to abandon the current analysis function and resume execution of the calling thread at a new application register state. Note that this API does not return back to the caller's analysis function.
This API can be called from an analysis function or a replacement routine, but not from a callback.
The signal handler is considered a callback. You can only use PIN_ExecuteAt in an analysis function or a replacement routine.
One thing you may try to do is to save the context you are interested in and allow the application to resume, ensuring that the next instruction to be executed has an analysis callback attached. You may be able to use if-then instrumentation to improve performance. Then you can call ExecuteAt from that analysis routine.
I've been playing with sigaction in the nix-rust crate to try and handle a SIGINT signal in my program and instead do nothing. While I've been able to handle the signal using:
let sig_action = signal::SigAction::new(
handle_signal,
signal::SockFlag::empty(),
signal::SigSet::empty()
);
unsafe { signal::sigaction(signal::SIGINT, &sig_action); }
It seems no matter what I do in the handle_signal function, when it concludes, the SIGINT is still processed and the program exits. My handler does not replace the default functionality, rather it happens before it. What would the function have to do to instead prevent the interrupt from still causing the program to exit?
Are you using cargo run to run your program? If so, it sounds like your program is handling the SIGINT signal and instead cargo is being killed. Since cargo doesn't have any special handling it is being killed by the signal, thus ending your program.
When using a serial port via POSIX, it's recommended to save the original attributes using tcgetattr() before changing them with tcsetattr(), and then restore them before closing the port. What about when a program is terminated by pressing control-C or when the program receives SIGINT? I haven't seen this covered in any of the serial tutorials.
Apparently an atexit() function wouldn't be sufficient, because it's not called by the default SIGINT handler. So it seems installation of a signal handler would be necessary that restores the attributes to any serial ports still open. Is it even safe to call tcsetattr() from a signal handler?
One might simply dismiss this issue as insignificant, but it's common to terminate a program with control-C, especially one that can take tens of seconds to complete operations. If it's OK not to preserve serial port settings in this case, then there seems little reason to preserve them at all. If anything, it might be better not to bother, rather than do it inconsistently.
I found some examples of source code doing the above, but nothing well-documented. I guess I'm interested in some discussion of whether this is a good idea. Thanks.
After further research I think I've answered this to my satisfaction.
First, in the man page for signal I noticed that a signal handler is specifically allowed to call tcsetattr(), along with a few others:
The signal handler routine must be very careful, since processing elsewhere was interrupted at some arbitrary point. POSIX has the concept of "safe function". If a signal interrupts an unsafe function, and handler calls an unsafe function, then the behavior is undefined. Safe functions are listed explicitly in the various standards. The POSIX.1-2003 list is ... `raise()` ... `signal()` ... `tcsetattr()` [trimmed to relevant ones]
This strongly suggests that the POSIX committee had this exact kind of thing in mind, and leads to a straight forward approach where you change the SIGINT handler once you've opened serial and saved its attributes, then in your handler, restore them and the old SIGINT handler, then re-raise the signal:
static void (*prev_sigint)( int );
static termios saved_attr;
static int fd;
static void cleanup( int ignored )
{
tcsetattr( fd, TCSANOW, &saved_attr );
signal( SIGINT, prev_sigint );
raise( SIGINT );
}
int main( void )
{
open_serial_and_save_attrs();
prev_sigint = signal( SIGINT, cleanup );
...
}
Recently ,I come across this problem as I memtioned in this Title.
I have tried by using QThread::terminate(),but I just can NOT stop
the thread ,which is in a dead loop (let's say,while(1)).
thanks a lot.
Terminating the thread is the easy solution to stopping an async operation, but it is usually a bad idea: the thread could be doing a system call or could be in the middle of updating a data structure when it is terminated, which could leave the program or even the OS in an unstable state.
Try to transform your while(1) into while( isAlive() ) and make isAlive() return false when you want the thread to exit.
QThreads can deadlock if they finish "naturally" during termination.
For example in Unix, if the thread is waiting on a "read" call, the termination attempt (a Unix signal) will make the "read" call abort with an error code before the thread is destroyed.
That means that the thread can still reach it's natural exit point while being terminated. When it does so, a deadlock is reached since some internal mutex is already locked by the "terminate" call.
My workaround is to actually make sure that the thread never returns if it was terminated.
while( read(...) > 0 ) {
// Do stuff...
}
while( wasTerminated )
sleep(1);
return;
wasTerminated here is actually implemented a bit more complex, using atomic ints:
enum {
Running, Terminating, Quitting
};
QAtomicInt _state; // Initialized to Running
void myTerminate()
{
if( _state.testAndSetAquire(Running, Terminating) )
terminate();
}
void run()
{
[...]
while(read(...) > 0 ) {
[...]
}
if( !_state.testAndSetAquire(Running, Quitting) ) {
for(;;) sleep(1);
}
}
Have you tried exit or quit?
Did the thread call QThread::setTerminationEnabled(false)? That would cause thread termination to delay indefinitely.
EDIT: I don't know what platform you're on, but I checked the Windows implementation of QThread::terminate. Assuming the thread was actually running to begin with, and termination wasn't disabled via the above function, it's basically a wrapper around TerminateThread() in the Windows API. This function accepts disrespect from no thread, and tends to leave a mess behind with resource leaks and similar dangling state. If it's not killing the thread, you're either dealing with zombie kernel calls (most likely blocked I/O) or have even bigger problems somewhere.
To use unnamed pipes
int gPipeFdTest[2]; //create a global integer array
As an when where you intend to create pipes use
if( pipe(gPipeFdTest) < 0)
{
perror("Pipe failed");
exit(1);
}
The above code will create a pipe which has two ends gPipeFdTest[0] for reading and gPipeFdTest[1] for writing. What you can do is in your run function set up to read the pipe using select system call. And from where you want to come out of run, there set up to write using write system call. I have used select system call for monitoring the read end of the pipe as it suits my implmentation. Try to figure all this out in your case. If you need any more help, give me a buzz.
Edit:
My problem was just like yours. I had a while(1) loop and the other things I tried needed mutexes and other fancy multithreading mumbo jumbo, which added complexity and debugging was nightmare. Using pipes absolved me from those complexities besides simplified the code. I am not saying that it is the best option but in my case it turned out to be the best and cleanest alternative. I was bugged my hung application before this solution.