<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/sync/notifier/base/async_network_alive.h"

#include <sys/socket.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>

#include "base/logging.h"
#include "talk/base/physicalsocketserver.h"

namespace notifier {

class AsyncNetworkAliveLinux : public AsyncNetworkAlive {
 public:
  AsyncNetworkAliveLinux() {
    if (pipe(exit_pipe_) == -1) {
      PLOG(ERROR) << "Could not create pipe for exit signal.";
      exit_pipe_[0] = 0;
      exit_pipe_[1] = 0;
    }
  }

  virtual ~AsyncNetworkAliveLinux() {
    if (exit_pipe_[1]) {
      close(exit_pipe_[1]);
    }
  }

 protected:
  // SignalThread Interface
  virtual void DoWork() {
    if (!exit_pipe_[0]) {
      // If we don't have an exit flag to listen for, set the error flag and
      // abort.
      error_ = true;
      return;
    }

    // This function listens for changes to network interfaces, and link state.
    // It's copied from syncapi.cc.
    struct sockaddr_nl socket_address;

    memset(&socket_address, 0, sizeof(socket_address));
    socket_address.nl_family = AF_NETLINK;
    socket_address.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;

    // NETLINK_ROUTE is the protocol used to update the kernel routing table.
    int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    bind(fd, (struct sockaddr *) &socket_address, sizeof(socket_address));

    fd_set rdfs;
    FD_ZERO(&rdfs);
    FD_SET(fd, &rdfs);
    FD_SET(exit_pipe_[0], &rdfs);

    int max_fd = fd > exit_pipe_[0] ? fd : exit_pipe_[0];

    int result = select(max_fd + 1, &rdfs, NULL, NULL, NULL);

    if (result <= 0) {
      error_ = true;
      PLOG(ERROR) << "select() returned unexpected result " << result;
      close(fd);
      close(exit_pipe_[0]);
      return;
    }

    // Since we received a change from the socket, read the change in.
    if (FD_ISSET(fd, &rdfs)) {
      char buf[4096];
      struct iovec iov = { buf, sizeof(buf) };
      struct sockaddr_nl sa;

      struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
      recvmsg(fd, &msg, 0);
    }

    close(fd);

    // If exit_pipe was written to, we must be shutting down.
    if (FD_ISSET(exit_pipe_[0], &rdfs)) {
      alive_ = false;
      error_ = true;
      close(exit_pipe_[0]);
      return;
    }

    // If there is an active connection, check that talk.google.com:5222
    // is reachable.
    talk_base::PhysicalSocketServer physical;
    scoped_ptr<talk_base::Socket> socket(physical.CreateSocket(SOCK_STREAM));
    if (socket->Connect(talk_base::SocketAddress("talk.google.com", 5222))) {
      alive_ = false;
    } else {
      alive_ = true;
    }
  }

  virtual void OnWorkStop() {
    if (exit_pipe_[1]) {
      char data = 0;<commit_msg>Clean up read FDs in async network alive.  This prevents chrome from eating all FDs.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/sync/notifier/base/async_network_alive.h"

#include <sys/socket.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>

#include "base/logging.h"
#include "talk/base/physicalsocketserver.h"

namespace notifier {

class AsyncNetworkAliveLinux : public AsyncNetworkAlive {
 public:
  AsyncNetworkAliveLinux() {
    if (pipe(exit_pipe_) == -1) {
      PLOG(ERROR) << "Could not create pipe for exit signal.";
      exit_pipe_[0] = 0;
      exit_pipe_[1] = 0;
    }
  }

  virtual ~AsyncNetworkAliveLinux() {
    if (exit_pipe_[1]) {
      // Ensure that we've signalled the thread to quit.
      char data = 0;
      if (write(exit_pipe_[1], &data, 1) == -1) {
        PLOG(WARNING) << "Error sending error signal to AsyncNetworkAliveLinux";
      }
      close(exit_pipe_[1]);
      exit_pipe_[1] = 0;
    }
    if (exit_pipe_[0]) {
      close(exit_pipe_[0]);
      exit_pipe_[0] = 0;
    }
  }

 protected:
  // SignalThread Interface
  virtual void DoWork() {
    if (!exit_pipe_[0]) {
      PLOG(ERROR) << "No exit flag to listen for.";
      // If we don't have an exit flag to listen for, set the error flag and
      // abort.
      error_ = true;
      return;
    }

    // This function listens for changes to network interfaces, and link state.
    // It's copied from syncapi.cc.
    struct sockaddr_nl socket_address;

    memset(&socket_address, 0, sizeof(socket_address));
    socket_address.nl_family = AF_NETLINK;
    socket_address.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;

    // NETLINK_ROUTE is the protocol used to update the kernel routing table.
    int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    bind(fd, (struct sockaddr *) &socket_address, sizeof(socket_address));

    fd_set rdfs;
    FD_ZERO(&rdfs);
    FD_SET(fd, &rdfs);
    FD_SET(exit_pipe_[0], &rdfs);

    int max_fd = fd > exit_pipe_[0] ? fd : exit_pipe_[0];

    int result = select(max_fd + 1, &rdfs, NULL, NULL, NULL);

    if (result <= 0) {
      error_ = true;
      PLOG(ERROR) << "select() returned unexpected result " << result;
      close(fd);
      close(exit_pipe_[0]);
      exit_pipe_[0] = 0;
      return;
    }

    // Since we received a change from the socket, read the change in.
    if (FD_ISSET(fd, &rdfs)) {
      char buf[4096];
      struct iovec iov = { buf, sizeof(buf) };
      struct sockaddr_nl sa;

      struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
      recvmsg(fd, &msg, 0);
    }

    close(fd);

    // If exit_pipe was written to, we must be shutting down.
    if (exit_pipe_[0] == 0 || FD_ISSET(exit_pipe_[0], &rdfs)) {
      alive_ = false;
      error_ = true;
      close(exit_pipe_[0]);
      exit_pipe_[0] = 0;
      return;
    }

    // If there is an active connection, check that talk.google.com:5222
    // is reachable.
    talk_base::PhysicalSocketServer physical;
    scoped_ptr<talk_base::Socket> socket(physical.CreateSocket(SOCK_STREAM));
    if (socket->Connect(talk_base::SocketAddress("talk.google.com", 5222))) {
      alive_ = false;
    } else {
      alive_ = true;
    }

    close(exit_pipe_[0]);
    exit_pipe_[0] = 0;
  }

  virtual void OnWorkStop() {
    if (exit_pipe_[1]) {
      char data = 0;
{'fraction_non_alphanumeric': 0.1254847215759268, 'fraction_numerical': 0.015355979525360632, 'mean_word_length': 2.875, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4333560', 'n_tokens_mistral': 2286, 'n_tokens_neox': 2168, 'n_words': 599}