This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
struct winbindd_response *response;
void (*continuation)(void *private_data, BOOL success);
struct timed_event *reply_timeout_event;
+ pid_t child_pid; /* pid of the child we're waiting on. Used to detect
+ a restart of the child (child->pid != child_pid). */
void *private_data;
};
struct winbindd_async_request *state =
talloc_get_type_abort(private_data, struct winbindd_async_request);
- /* Deal with the reply - set to error. */
+ DEBUG(0,("async_request_timeout_handler: child pid %u is not responding. "
+ "Closing connection to it.\n",
+ state->child_pid ));
+ /* Deal with the reply - set to error. */
async_reply_recv(private_data, False);
+}
- /*
- * Close the socket to the child. Should cause the
- * child to exit.
- */
+/**************************************************************
+ Common function called on both async send and recv fail.
+ Cleans up the child and schedules the next request.
+**************************************************************/
- DEBUG(0,("async_request_timeout_handler: child pid %u is not responding. "
- "Closing connection to it.\n",
- state->child->pid ));
+static void async_request_fail(struct winbindd_async_request *state)
+{
+ DLIST_REMOVE(state->child->requests, state);
+
+ TALLOC_FREE(state->reply_timeout_event);
+
+ SMB_ASSERT(state->child_pid != (pid_t)0);
- winbind_child_died(state->child->pid);
+ /* If not already reaped, send kill signal to child. */
+ if (state->child->pid == state->child_pid) {
+ kill(state->child_pid, SIGTERM);
+
+ /*
+ * Close the socket to the child.
+ */
+ winbind_child_died(state->child_pid);
+ }
+
+ state->response->length = sizeof(struct winbindd_response);
+ state->response->result = WINBINDD_ERROR;
+ state->continuation(state->private_data, False);
}
static void async_request_sent(void *private_data_data, BOOL success)
{
- uint32_t timeout;
struct winbindd_async_request *state =
talloc_get_type_abort(private_data_data, struct winbindd_async_request);
if (!success) {
- DEBUG(5, ("Could not send async request\n"));
-
- state->response->length = sizeof(struct winbindd_response);
- state->response->result = WINBINDD_ERROR;
- state->continuation(state->private_data, False);
+ DEBUG(5, ("Could not send async request to child pid %u\n",
+ (unsigned int)state->child_pid ));
+ async_request_fail(state);
return;
}
sizeof(state->response->result),
async_reply_recv, state);
- timeout = 30;
-
- if (state->request->cmd == WINBINDD_PAM_AUTH
- || state->request->cmd == WINBINDD_PAM_AUTH_CRAP ) {
-
- /*
- * Normal timeouts are 30s, but auth requests may take a long
- * time to timeout.
- */
-
- timeout = 300;
- }
-
/*
- * Set up a timeout of for the response. If we don't get it close the
- * child socket and report failure.
+ * Set up a timeout of 300 seconds for the response.
+ * If we don't get it close the child socket and
+ * report failure.
*/
- state->reply_timeout_event = event_add_timed(
- winbind_event_context(),
- NULL,
- timeval_current_ofs(timeout,0),
- "async_request_timeout",
- async_request_timeout_handler,
- state);
-
+ state->reply_timeout_event = event_add_timed(winbind_event_context(),
+ NULL,
+ timeval_current_ofs(300,0),
+ "async_request_timeout",
+ async_request_timeout_handler,
+ state);
if (!state->reply_timeout_event) {
- smb_panic("async_request_sent: failed to add timeout "
- "handler.\n");
+ smb_panic("async_request_sent: failed to add timeout handler.\n");
}
}
talloc_get_type_abort(private_data, struct winbindd_async_request);
struct winbindd_child *child = state->child;
- if (state->reply_timeout_event) {
- TALLOC_FREE(state->reply_timeout_event);
- }
+ TALLOC_FREE(state->reply_timeout_event);
state->response->length = sizeof(struct winbindd_response);
if (!success) {
- DEBUG(5, ("Could not receive async reply\n"));
-
- cache_cleanup_response(child->pid);
- DLIST_REMOVE(child->requests, state);
+ DEBUG(5, ("Could not receive async reply from child pid %u\n",
+ (unsigned int)state->child_pid ));
- state->response->result = WINBINDD_ERROR;
- state->continuation(state->private_data, False);
+ cache_cleanup_response(state->child_pid);
+ async_request_fail(state);
return;
}
- SMB_ASSERT(cache_retrieve_response(child->pid,
+ SMB_ASSERT(cache_retrieve_response(state->child_pid,
state->response));
- cache_cleanup_response(child->pid);
+ cache_cleanup_response(state->child_pid);
DLIST_REMOVE(child->requests, state);
return;
}
+ /* Now we know who we're sending to - remember the pid. */
+ request->child_pid = child->pid;
+
setup_async_write(&child->event, request->request,
sizeof(*request->request),
async_main_request_sent, request);
}
if (child == NULL) {
- DEBUG(0, ("Unknown child %d died!\n", pid));
+ DEBUG(5, ("Already reaped child %u died\n", (unsigned int)pid));
return;
}
}
}
+void winbind_msg_dump_event_list(struct messaging_context *msg_ctx,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id,
+ DATA_BLOB *data)
+{
+ struct winbindd_child *child;
+
+ DEBUG(10,("winbind_msg_dump_event_list received\n"));
+
+ dump_event_list(winbind_event_context());
+
+ for (child = children; child != NULL; child = child->next) {
+
+ DEBUG(10,("winbind_msg_dump_event_list: sending message to pid %u\n",
+ (unsigned int)child->pid));
+
+ messaging_send_buf(msg_ctx, pid_to_procid(child->pid),
+ MSG_DUMP_EVENT_LIST,
+ NULL, 0);
+ }
+
+}
static void account_lockout_policy_handler(struct event_context *ctx,
struct timed_event *te,
DEBUG(10,("account_lockout_policy_handler called\n"));
- if (child->lockout_policy_event) {
- TALLOC_FREE(child->lockout_policy_event);
- }
+ TALLOC_FREE(child->lockout_policy_event);
if ( !winbindd_can_contact_domain( child->domain ) ) {
DEBUG(10,("account_lockout_policy_handler: Removing myself since I "
talloc_destroy(mem_ctx);
}
+static void child_msg_dump_event_list(struct messaging_context *msg,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id,
+ DATA_BLOB *data)
+{
+ DEBUG(5,("child_msg_dump_event_list received\n"));
+
+ dump_event_list(winbind_event_context());
+}
+
+
static BOOL fork_domain_child(struct winbindd_child *child)
{
int fdpair[2];
MSG_WINBIND_ONLINE, NULL);
messaging_deregister(winbind_messaging_context(),
MSG_WINBIND_ONLINESTATUS, NULL);
+ messaging_deregister(winbind_messaging_context(),
+ MSG_DUMP_EVENT_LIST, NULL);
/* Handle online/offline messages. */
messaging_register(winbind_messaging_context(), NULL,
MSG_WINBIND_ONLINE, child_msg_online);
messaging_register(winbind_messaging_context(), NULL,
MSG_WINBIND_ONLINESTATUS, child_msg_onlinestatus);
+ messaging_register(winbind_messaging_context(), NULL,
+ MSG_DUMP_EVENT_LIST, child_msg_dump_event_list);
if ( child->domain ) {
child->domain->startup = True;
for (domain = domain_list(); domain; domain = domain->next) {
if (domain != child->domain) {
- if (domain->check_online_event) {
- TALLOC_FREE(domain->check_online_event);
- }
+ TALLOC_FREE(domain->check_online_event);
}
}