Subversion Repositories public

Rev

Rev 108 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
69 luk 1
 
2
/// Application instance class implementation
3
/**
4
 * \file appinst.cpp
5
 *
108 luk 6
 * Copyright (C) 2007, 2008, 2012 Lukas Jelinek, <lukas@aiken.cz>
69 luk 7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of one of the following licenses:
10
 *
11
 * \li 1. X11-style license (see LICENSE-X11)
12
 * \li 2. GNU Lesser General Public License, version 2.1 (see LICENSE-LGPL)
13
 * \li 3. GNU General Public License, version 2  (see LICENSE-GPL)
14
 *
15
 * If you want to help with choosing the best license for you,
16
 * please visit http://www.gnu.org/licenses/license-list.html.
17
 *
108 luk 18
 * Credits:
19
 *   Christian Ruppert (new include to build with GCC 4.4+)
20
 *
69 luk 21
 */
22
 
23
 
24
#include <fcntl.h>
25
#include <unistd.h>
26
#include <errno.h>
27
#include <signal.h>
108 luk 28
#include <cstdio>
69 luk 29
 
30
#include "appinst.h"
31
 
73 luk 32
/// Lockfile permissions (currently 0644)
33
#define APPLOCK_PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
69 luk 34
 
35
 
71 luk 36
AppInstance::AppInstance(const std::string& rName, const std::string& rBase)
37
: m_fLocked(false)
69 luk 38
{
71 luk 39
  std::string base(rBase);
40
  if (base.empty())
41
    base = APPLOCK_BASEDIR;
69 luk 42
 
71 luk 43
  if (base[base.length()-1] == '/')
44
    m_path = base + rName + ".pid";
45
  else
46
    m_path = base + "/" + rName + ".pid";
69 luk 47
}
48
 
49
AppInstance::~AppInstance()
50
{
51
  try {
52
    Unlock();
53
  } catch (AppInstException e) {}
54
}
55
 
71 luk 56
bool AppInstance::DoLock()
69 luk 57
{
73 luk 58
  int fd = open(m_path.c_str(), O_WRONLY | O_CREAT | O_EXCL, APPLOCK_PERM);
69 luk 59
  if (fd != -1) {
60
    FILE* f = fdopen(fd, "w");
61
    if (f == NULL) {
62
      AppInstException e(errno);
63
      close(fd);
64
      throw e;
65
    }
66
 
67
    if (fprintf(f, "%u", (unsigned) getpid()) <= 0) {
68
      AppInstException e(errno);
69
      fclose(f);
70
      throw e;
71
    }
72
 
73
    if (fclose(f) != 0)
74
      throw AppInstException(errno);
75
 
76
    m_fLocked = true;  
77
    return true;
78
  }
79
 
80
  if (errno != EEXIST)
81
    throw AppInstException(errno);
82
 
83
  return false;
84
}
85
 
86
bool AppInstance::Lock()
87
{
88
  for (int i=0; i<100; i++) {
71 luk 89
    if (DoLock())
69 luk 90
      return true;
91
 
71 luk 92
    FILE* f = fopen(m_path.c_str(), "r");
69 luk 93
    if (f == NULL) {
94
      if (errno != ENOENT)
95
        throw AppInstException(errno);
96
    }
97
    else {
98
      unsigned pid;
99
      ssize_t len = fscanf(f, "%u", &pid);
100
      if (len == -1) {
101
        AppInstException e(errno);
102
        fclose(f);
103
        throw e;
104
      }
105
      else if (len == 0) {
106
        AppInstException e(EIO);
107
        fclose(f);
108
        throw e;
109
      }
110
 
111
      fclose(f);
112
 
113
      int res = kill((pid_t) pid, 0);
114
      if (res == 0)
115
        return false;
116
 
117
      if (errno != ESRCH)
118
        throw AppInstException(errno);
119
 
71 luk 120
      res = unlink(m_path.c_str());
69 luk 121
      if (res != 0 && errno != ENOENT)
122
        throw AppInstException(errno);
123
    }
124
  }
125
 
126
  return false;
127
}
128
 
129
void AppInstance::Unlock()
130
{
131
  if (!m_fLocked)
132
    return;
133
 
71 luk 134
  if (unlink(m_path.c_str()) != 0 && errno != ENOENT)
69 luk 135
    throw AppInstException(errno);
136
 
137
  m_fLocked = false;
138
}
139
 
140
bool AppInstance::Exists() const
141
{
142
  if (m_fLocked)
143
    return true;
144
 
71 luk 145
  FILE* f = fopen(m_path.c_str(), "r");
69 luk 146
  if (f == NULL) {
147
    if (errno == ENOENT)
148
      return false;
149
    else
150
      throw AppInstException(errno);
151
  }
152
 
153
  bool ok = false;
154
 
155
  unsigned pid;
156
  if (fscanf(f, "%u", &pid) == 1) {
157
    if (kill((pid_t) pid, 0) == 0)
158
      ok = true;
159
    else if (errno != ESRCH) {
160
      AppInstException e(errno);
161
      fclose(f);
162
      throw e;
163
    }
164
  }
165
 
166
  fclose(f);
167
 
168
  return ok;
169
}
170
 
171
bool AppInstance::SendSignal(int iSigNo) const
172
{
71 luk 173
  FILE* f = fopen(m_path.c_str(), "r");
69 luk 174
  if (f == NULL) {
175
    if (errno == ENOENT)
176
      return false;
177
    else
178
      throw AppInstException(errno);
179
  }
180
 
181
  bool ok = false;
182
 
183
  unsigned pid;
184
  if (fscanf(f, "%u", &pid) == 1) {
185
    if (pid != (unsigned) getpid()) {
186
      if (kill((pid_t) pid, iSigNo) == 0) {
187
        ok = true;
188
      }
189
      else if (errno != ESRCH) {
190
        AppInstException e(errno);
191
        fclose(f);
192
        throw e;
193
      }
194
    }
195
  }
196
 
197
  fclose(f);
198
 
199
  return ok;
200
}
201