-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
zmq_ctx_term throws Assertion failed: pfd.revents & POLLIN (src/signaler.cpp:226) #1307
Comments
I'm assuming this is Linux? signaler.cpp:226 is - zmq_assert (pfd.revents & POLLIN); But, Linux may, in addition to the requested events, also signal POLLERR, so I think strictly asserting on POLLIN here may be the wrong thing to do. On Fri, Jan 16, 2015 at 4:44 AM, Uli Riehm notifications@github.com wrote:
|
Hm okay, I'll try |
I don't think there's anything to really to try here. This is a possible On Fri, Jan 16, 2015 at 3:05 PM, Uli Riehm notifications@github.com wrote:
|
Well no ;-) |
I'm getting this error just in the Interrupt example. If you run I believe that Now this is the error (when calling
on Windows:
|
The deadlock is (almost always) due to one or more open sockets, or sockets On Sat, Jan 24, 2015 at 1:12 AM, Uli Riehm notifications@github.com wrote:
|
Well... It's just the zmq_ctx_term example which does assert. Don't get me wrong, but I don't care about LINGER values and running sockets... I just want to terminate, from another thread, from the same thread; I don't need that assert ;-) The example doesn't make sense, if I'm just waiting for CTRL+C and then go out clean. I need to run zmq.ctx_term in the middle of a Receive/Send operation, which then should return -1, errno = ETERM. Oh I see now zmq_ctx_shutdown... is that I'm looking for? YES, it works for now... You do now However, I don't exactly know because I'm not "in the code" so... it's bad to have a sigabort. |
Can you get a C example that provokes this? On Sat, Jan 24, 2015 at 3:48 PM, Uli Riehm notifications@github.com wrote:
|
Well I'm not a good C programmer... // Shows how to handle Ctrl-C
#include <zmq.h>
#include <stdio.h>
#include <signal.h>
// Signal handling
//
// Call s_catch_signals() in your application at startup, and then
// exit your main loop if s_interrupted is ever 1. Works especially
// well with zmq_poll.
static int s_interrupted = 0;
static void s_signal_handler (int signal_value)
{
s_interrupted = 1;
}
#ifndef WIN32
static void s_catch_signals (void)
{
struct sigaction action;
action.sa_handler = s_signal_handler;
action.sa_flags = 0;
sigemptyset (&action.sa_mask);
sigaction (SIGINT, &action, NULL);
sigaction (SIGTERM, &action, NULL);
}
#endif
int main (void)
{
void *context = zmq_ctx_new ();
void *socket = zmq_socket (context, ZMQ_REP);
zmq_bind (socket, "tcp://*:5555");
#ifndef WIN32
s_catch_signals ();
#else
signal (SIGINT, s_signal_handler);
signal (SIGTERM, s_signal_handler);
#endif
while (1)
{
if (s_interrupted) {
s_interrupted = 0;
printf ("W: interrupt received, shutting down server...\n");
if (-1 == zmq_ctx_shutdown(context)) {
errno = zmq_errno();
printf ("E: (%d) %s\n", errno, strerror(errno));
break;
}
}
char buffer [255];
int rc = zmq_recv (socket, buffer, 255, ZMQ_DONTWAIT);
if (rc == -1) {
errno = zmq_errno();
if (errno == EAGAIN) {
continue;
}
if (errno == ETERM) {
printf ("I: Terminated!\n");
break;
}
printf ("E: (%d) %s\n", errno, strerror(errno));
break;
}
rc = zmq_send(socket, "Hello", 5, 0);
if (rc == -1) {
errno = zmq_errno();
if (errno == ETERM) {
printf ("I: Terminated!\n");
break;
}
printf ("E: (%i) %s\n", errno, strerror(errno));
break;
}
}
zmq_close (socket);
zmq_ctx_destroy (context);
return 0;
} Ah, and you have to replace zmq_ctx_shutdown with zmq_ctx_term to (possibly) get the abort... I'm removing this from my disk. Please try the C# edition... (Install |
By "works on Windows" do you mean exhibits the assert? On Sun, Jan 25, 2015 at 2:16 PM, Uli Riehm notifications@github.com wrote:
|
No, I didn't get the signalling correct, on Windows it did work (with errno = zmq_errno()), on Linux I didn't get it running. Please take the hwserver example, make it DONTWAIT and try to catch the SIGINT. When getting a SIGINT, usually you would do ctx_shutdown, however the assert is coming if you do ctx_term instead. |
I believe you shouldn't I am now setting |
Hi, I got the same crash in signaler.cpp:226 with 4.1.0, this patch seems fixing it diff --git a/src/signaler.cpp b/src/signaler.cpp
index 25667bf..ba5b288 100644
--- a/src/signaler.cpp
+++ b/src/signaler.cpp
@@ -223,6 +223,11 @@ int zmq::signaler_t::wait (int timeout_)
}
#endif
zmq_assert (rc == 1);
+ if (pfd.revents & POLLNVAL)
+ {
+ errno=EINTR;
+ return -1;
+ }
zmq_assert (pfd.revents & POLLIN);
return 0;
diff --git a/src/mailbox.cpp b/src/mailbox.cpp
index bd140a4..da50cf0 100644
--- a/src/mailbox.cpp
+++ b/src/mailbox.cpp
@@ -67,14 +67,18 @@ int zmq::mailbox_t::recv (command_t *cmd_, int timeout_)
}
// Wait for signal from the command sender.
- const int rc = signaler.wait (timeout_);
+ int rc = signaler.wait (timeout_);
if (rc == -1) {
errno_assert (errno == EAGAIN || errno == EBADF);
return -1;
}
// Receive the signal.
- signaler.recv ();
+ rc=signaler.recv ();
+ if (rc == -1) {
+ errno_assert (errno == EINTR);
+ return -1;
+ }
// Switch into active state.
active = true;
diff --git a/src/signaler.cpp b/src/signaler.cpp
index ba5b288..a9609df 100644
--- a/src/signaler.cpp
+++ b/src/signaler.cpp
@@ -265,12 +265,17 @@ int zmq::signaler_t::wait (int timeout_)
#endif
}
-void zmq::signaler_t::recv ()
+int zmq::signaler_t::recv ()
{
// Attempt to read a signal.
#if defined ZMQ_HAVE_EVENTFD
uint64_t dummy;
ssize_t sz = read (r, &dummy, sizeof (dummy));
+ if (sz==0 || (sz==-1 && errno==EINVAL))
+ {
+ errno=EINTR;
+ return -1;
+ }
errno_assert (sz == sizeof (dummy));
// If we accidentally grabbed the next signal along with the current
@@ -279,7 +284,7 @@ void zmq::signaler_t::recv ()
const uint64_t inc = 1;
ssize_t sz2 = write (w, &inc, sizeof (inc));
errno_assert (sz2 == sizeof (inc));
- return;
+ return 0;
}
zmq_assert (dummy == 1);
@@ -295,6 +300,7 @@ void zmq::signaler_t::recv ()
zmq_assert (nbytes == sizeof (dummy));
zmq_assert (dummy == 0);
#endif
+ return 0;
}
#ifdef HAVE_FORK
diff --git a/src/signaler.hpp b/src/signaler.hpp
index b66f0ae..54a271d 100644
--- a/src/signaler.hpp
+++ b/src/signaler.hpp
@@ -44,7 +44,7 @@ namespace zmq
fd_t get_fd () const;
void send ();
int wait (int timeout_);
- void recv ();
+ int recv ();
#ifdef HAVE_FORK
// close the file descriptors in a forked child process so that they
--
1.8.4.GIT Race condition in ctx destroy (presumably also in *_term) when sending to socket from this context may be provoked with utilising CPU on max. I could reproduce it several times. |
Was this fixed in the end? |
I ran into this in our codebase where it was closing sockets where it should have been terminating the context instead. |
This issue has been automatically marked as stale because it has not had activity for 365 days. It will be closed if no further activity occurs within 56 days. Thank you for your contributions. |
was autoclosed, but still occurs? |
Can this be reopened? It's still occurring. |
As the documentation states ZMQ_LINGER should be set to an none infinate value so this does not happen it is up to the user of the libary to decide which. I personaly set it to the half of ZMQ_RCVTIMEO see the warning in https://libzmq.readthedocs.io/en/zeromq4-x/zmq_ctx_term.html for more info. |
When I'm terminating my context, the program throws
Assertion failed: pfd.revents & POLLIN (src/signaler.cpp:226)
as SIGABORT.And also sometimes
pure virtual method called, terminate called without an active exception
Any thoughts...?
The text was updated successfully, but these errors were encountered: