summaryrefslogtreecommitdiffstats
path: root/chrome/browser/process_singleton_linux.cc
blob: 57a65315e4b0ddd60202f338ea4e902aacb547c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// Copyright (c) 2009 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/process_singleton.h"

#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#include "base/eintr_wrapper.h"
#include "base/logging.h"
#include "base/string_util.h"
#include "chrome/common/chrome_constants.h"

ProcessSingleton::ProcessSingleton(const FilePath& user_data_dir) {
  socket_path_ = user_data_dir.Append(chrome::kSingletonSocketFilename);
}

ProcessSingleton::~ProcessSingleton() {
}

bool ProcessSingleton::NotifyOtherProcess() {
  int sock;
  sockaddr_un addr;
  SetupSocket(&sock, &addr);

  if (HANDLE_EINTR(connect(sock, reinterpret_cast<sockaddr*>(&addr),
                           sizeof(addr))) < 0 &&
      (errno == ENOENT || errno == ECONNREFUSED)) {
    return false;  // Tell the caller there's nobody to notify.
  }

  // TODO(port): pass in info to the other process.
  // http://code.google.com/p/chromium/issues/detail?id=8073
  NOTIMPLEMENTED() << " don't know how to notify other process about us.";

  return true;  // We did our best, so we die here.
}

void ProcessSingleton::Create() {
  int sock;
  sockaddr_un addr;
  SetupSocket(&sock, &addr);

  if (unlink(socket_path_.value().c_str()) < 0)
    DCHECK_EQ(errno, ENOENT);

  if (bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0)
    LOG(ERROR) << "bind() failed: " << strerror(errno);

  if (listen(sock, 5) < 0)
    NOTREACHED() << "listen failed: " << strerror(errno);

  // TODO(port): register this socket as something we care about getting
  // input on, process messages, etc.
  // http://code.google.com/p/chromium/issues/detail?id=8073
}

void ProcessSingleton::SetupSocket(int* sock, struct sockaddr_un* addr) {
  *sock = socket(PF_UNIX, SOCK_STREAM, 0);
  if (*sock < 0)
    LOG(FATAL) << "socket() failed: " << strerror(errno);

  addr->sun_family = AF_UNIX;
  if (socket_path_.value().length() > sizeof(addr->sun_path) - 1)
    LOG(FATAL) << "Socket path too long: " << socket_path_.value();
  base::strlcpy(addr->sun_path, socket_path_.value().c_str(),
                sizeof(addr->sun_path));
}