return fd_updt != NULL;
}
+static int precreated_poller_pipes[MAX_THREADS][2];
+
+/*
+ * Create the pipes before we create the threads, as they may not share
+ * their file descriptor tables.
+ */
+int fd_precreate_poller_pipes(void)
+{
+ int i;
+
+ for (i = 0; i < global.nbthread; i++) {
+ if (pipe(precreated_poller_pipes[i]) < 0)
+ return 0;
+ }
+ return 1;
+}
+
/* Initialize the pollers per thread.*/
static int init_pollers_per_thread()
{
int mypipe[2];
- if (pipe(mypipe) < 0)
+ /*
+ * The master does not get to pre-create pipes, so do it
+ * now.
+ */
+ if (!master) {
+ mypipe[0] = precreated_poller_pipes[tid][0];
+ mypipe[1] = precreated_poller_pipes[tid][1];
+ }
+ else if (pipe(mypipe) < 0)
return 0;
poller_rd_pipe = mypipe[0];
/* the startup thread will be thread 1 */
ha_pthread[0] = pthread_self();
+ /* When FD tables are not shared between thread groups, the poller
+ * pipes of all threads must be created before any group unshares its
+ * FD table, so that they are inherited into every group's table and
+ * cross-group wake_thread() keeps working.
+ */
+ if (!fd_precreate_poller_pipes()) {
+ ha_alert("Failed to create the poller pipes.\n");
+ exit(1);
+ }
+
/* Create one initial thread for each extra thread group. These will
* each be responsible for creating their own extra threads. The first
* group's initial thread is the current thread.