s3:nmbd: convert the asyncdns child handling to use tevent
authorStefan Metzmacher <metze@samba.org>
Thu, 21 Feb 2013 15:46:32 +0000 (16:46 +0100)
committerStefan Metzmacher <metze@samba.org>
Tue, 26 Feb 2013 15:44:06 +0000 (16:44 +0100)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
source3/nmbd/asyncdns.c
source3/nmbd/nmbd_packets.c
source3/nmbd/nmbd_proto.h

index 90340efe3970600195f9f2462da0303adbcbec76..aa6d6c00eb1a1ba20ac61c77a450e2d9f88963ba 100644 (file)
@@ -50,8 +50,14 @@ static struct name_record *add_dns_result(struct nmb_name *question, struct in_a
 
 #ifndef SYNC_DNS
 
-static int fd_in = -1, fd_out = -1;
-static pid_t child_pid = -1;
+struct asyncdns_state {
+       struct messaging_context *msg;
+       pid_t child_pid;
+       int fd_in;
+       struct tevent_fd *fde_in;
+       int fd_out;
+};
+static struct asyncdns_state *adns_state;
 static int in_dns;
 
 /* this is the structure that is passed between the parent and child */
@@ -72,11 +78,6 @@ static struct packet_struct *dns_current;
   loop
   ****************************************************************************/
 
-int asyncdns_fd(void)
-{
-       return fd_in;
-}
-
 /***************************************************************************
   handle DNS queries arriving from the parent
   ****************************************************************************/
@@ -90,7 +91,7 @@ static void asyncdns_process(void)
        while (1) {
                NTSTATUS status;
 
-               status = read_data(fd_in, (char *)&r, sizeof(r));
+               status = read_data(adns_state->fd_in, (char *)&r, sizeof(r));
 
                if (!NT_STATUS_IS_OK(status)) {
                        break;
@@ -99,7 +100,7 @@ static void asyncdns_process(void)
                pull_ascii_nstring( qname, sizeof(qname), r.name.name);
                r.result.s_addr = interpret_addr(qname);
 
-               if (write_data(fd_out, (char *)&r, sizeof(r)) != sizeof(r))
+               if (write_data(adns_state->fd_out, (char *)&r, sizeof(r)) != sizeof(r))
                        break;
        }
 
@@ -119,6 +120,26 @@ static void sig_term(int sig)
        _exit(0);
 }
 
+static int asyncdns_state_destructor(struct asyncdns_state *state)
+{
+       if (state->child_pid > 0) {
+               kill(state->child_pid, SIGTERM);
+               state->child_pid = -1;
+       }
+
+       TALLOC_FREE(state->fde_in);
+
+       if (state->fd_in != -1) {
+               close(state->fd_in);
+               state->fd_in = -1;
+       }
+       if (state->fd_out != -1) {
+               close(state->fd_out);
+               state->fd_out = -1;
+       }
+       return 0;
+}
+
 /***************************************************************************
  Called by the parent process when it receives a SIGTERM - also kills the
  child so we don't get child async dns processes lying around, causing trouble.
@@ -126,12 +147,14 @@ static void sig_term(int sig)
 
 void kill_async_dns_child(void)
 {
-       if (child_pid > 0) {
-               kill(child_pid, SIGTERM);
-               child_pid = -1;
-       }
+       TALLOC_FREE(adns_state);
 }
 
+static void asyncdns_run_queue(struct tevent_context *ev,
+                              struct tevent_fd *fde,
+                              uint16_t flags,
+                              void *private_data);
+
 /***************************************************************************
   create a child process to handle DNS lookups
   ****************************************************************************/
@@ -140,6 +163,18 @@ void start_async_dns(struct messaging_context *msg)
        int fd1[2], fd2[2];
        NTSTATUS status;
 
+       kill_async_dns_child();
+
+       adns_state = talloc_zero(msg, struct asyncdns_state);
+       if (adns_state == NULL) {
+               DEBUG(0,("can't allocate asyncdns state\n"));
+               return;
+       }
+       adns_state->msg = msg;
+       adns_state->fd_in = -1;
+       adns_state->fd_out = -1;
+       talloc_set_destructor(adns_state, asyncdns_state_destructor);
+
        CatchChild();
 
        if (pipe(fd1) || pipe(fd2)) {
@@ -147,19 +182,30 @@ void start_async_dns(struct messaging_context *msg)
                return;
        }
 
-       child_pid = fork();
+       adns_state->child_pid = fork();
 
-       if (child_pid) {
-               fd_in = fd1[0];
-               fd_out = fd2[1];
+       if (adns_state->child_pid) {
+               adns_state->fd_in = fd1[0];
+               adns_state->fd_out = fd2[1];
                close(fd1[1]);
                close(fd2[0]);
-               DEBUG(0,("started asyncdns process %d\n", (int)child_pid));
+               adns_state->fde_in = tevent_add_fd(nmbd_event_context(),
+                                                  adns_state,
+                                                  adns_state->fd_in,
+                                                  TEVENT_FD_READ,
+                                                  asyncdns_run_queue,
+                                                  NULL);
+               if (adns_state->fde_in == NULL) {
+                       DEBUG(0,("can't create asyncdns fde_in\n"));
+                       kill_async_dns_child();
+               }
+               DEBUG(0,("started asyncdns process %d\n",
+                       (int)adns_state->child_pid));
                return;
        }
 
-       fd_in = fd2[0];
-       fd_out = fd1[1];
+       adns_state->fd_in = fd2[0];
+       adns_state->fd_out = fd1[1];
 
        CatchSignal(SIGUSR2, SIG_IGN);
        CatchSignal(SIGUSR1, SIG_IGN);
@@ -195,35 +241,33 @@ static bool write_child(struct packet_struct *p)
 {
        struct query_record r;
 
+       if (adns_state == NULL) {
+               return false;
+       }
+
        r.name = p->packet.nmb.question.question_name;
 
-       return write_data(fd_out, (char *)&r, sizeof(r)) == sizeof(r);
+       return write_data(adns_state->fd_out, (char *)&r, sizeof(r)) == sizeof(r);
 }
 
 /***************************************************************************
   check the DNS queue
   ****************************************************************************/
-void run_dns_queue(struct messaging_context *msg)
+static void asyncdns_run_queue(struct tevent_context *ev,
+                              struct tevent_fd *fde,
+                              uint16_t flags,
+                              void *private_data)
 {
        struct query_record r;
        struct packet_struct *p, *p2;
        struct name_record *namerec;
        NTSTATUS status;
 
-       if (fd_in == -1)
-               return;
-
-       if (!process_exists_by_pid(child_pid)) {
-               close(fd_in);
-               close(fd_out);
-               start_async_dns(msg);
-       }
-
-       status = read_data(fd_in, (char *)&r, sizeof(r));
+       status = read_data(adns_state->fd_in, (char *)&r, sizeof(r));
 
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0, ("read from child failed: %s\n", nt_errstr(status)));
-               fd_in = -1;
+               start_async_dns(adns_state->msg);
                return;
        }
 
@@ -287,7 +331,7 @@ queue a DNS query
 
 bool queue_dns_query(struct packet_struct *p,struct nmb_name *question)
 {
-       if (in_dns || fd_in == -1)
+       if (in_dns || adns_state == NULL)
                return False;
 
        if (!dns_current) {
index 7a707a045b989ffeae62da8c6b4af926b0a75eaa..16f59e6461403f0a5e90c206baf1f17332f8f889 100644 (file)
@@ -1878,10 +1878,6 @@ bool listen_for_packets(struct messaging_context *msg, bool run_election)
 
        int pollrtn;
        int timeout;
-#ifndef SYNC_DNS
-       int dns_fd;
-       int dns_pollidx = -1;
-#endif
        struct processed_packet *processed_packet_list = NULL;
 
        if ((fds == NULL) || rescan_listen_set) {
@@ -1904,19 +1900,6 @@ bool listen_for_packets(struct messaging_context *msg, bool run_election)
        }
        num_sockets = listen_number;
 
-#ifndef SYNC_DNS
-       dns_fd = asyncdns_fd();
-       if (dns_fd != -1) {
-               fds = talloc_realloc(NULL, fds, struct pollfd, num_sockets+1);
-               if (fds == NULL) {
-                       return true;
-               }
-               dns_pollidx = num_sockets;
-               fds[num_sockets].fd = dns_fd;
-               num_sockets += 1;
-       }
-#endif
-
        for (i=0; i<num_sockets; i++) {
                fds[i].events = POLLIN|POLLHUP;
        }
@@ -1949,13 +1932,6 @@ bool listen_for_packets(struct messaging_context *msg, bool run_election)
                return False;
        }
 
-#ifndef SYNC_DNS
-       if ((dns_fd != -1) && (dns_pollidx != -1) &&
-           (fds[dns_pollidx].revents & (POLLIN|POLLHUP|POLLERR))) {
-               run_dns_queue(msg);
-       }
-#endif
-
        for(i = 0; i < listen_number; i++) {
                enum packet_type packet_type;
                struct packet_struct *packet;
index 4bcf100d5702154f6a4401ad156e800d9647971d..9c7f5b4ee33c0e9ab6b9703e690f0686bebfbec4 100644 (file)
 
 /* The following definitions come from nmbd/asyncdns.c  */
 
-int asyncdns_fd(void);
 void kill_async_dns_child(void);
 void start_async_dns(struct messaging_context *msg);
-void run_dns_queue(struct messaging_context *msg);
 bool queue_dns_query(struct packet_struct *p,struct nmb_name *question);
 bool queue_dns_query(struct packet_struct *p,struct nmb_name *question);
-void kill_async_dns_child(void);
 
 /* The following definitions come from nmbd/nmbd.c  */