Subversion Repositories public

Rev

Rev 69 | Rev 73 | Go to most recent revision | 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
 *
6
 * Copyright (C) 2007 Lukas Jelinek, <lukas@aiken.cz>
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
 *
18
 */
19
 
20
 
21
#include <fcntl.h>
22
#include <unistd.h>
23
#include <stdio.h>
24
#include <errno.h>
25
#include <signal.h>
26
 
27
#include "appinst.h"
28
 
29
 
30
 
71 luk 31
AppInstance::AppInstance(const std::string& rName, const std::string& rBase)
32
: m_fLocked(false)
69 luk 33
{
71 luk 34
  std::string base(rBase);
35
  if (base.empty())
36
    base = APPLOCK_BASEDIR;
69 luk 37
 
71 luk 38
  if (base[base.length()-1] == '/')
39
    m_path = base + rName + ".pid";
40
  else
41
    m_path = base + "/" + rName + ".pid";
69 luk 42
}
43
 
44
AppInstance::~AppInstance()
45
{
46
  try {
47
    Unlock();
48
  } catch (AppInstException e) {}
49
}
50
 
71 luk 51
bool AppInstance::DoLock()
69 luk 52
{
71 luk 53
  int fd = open(m_path.c_str(), O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
69 luk 54
  if (fd != -1) {
55
    FILE* f = fdopen(fd, "w");
56
    if (f == NULL) {
57
      AppInstException e(errno);
58
      close(fd);
59
      throw e;
60
    }
61
 
62
    if (fprintf(f, "%u", (unsigned) getpid()) <= 0) {
63
      AppInstException e(errno);
64
      fclose(f);
65
      throw e;
66
    }
67
 
68
    if (fclose(f) != 0)
69
      throw AppInstException(errno);
70
 
71
    m_fLocked = true;  
72
    return true;
73
  }
74
 
75
  if (errno != EEXIST)
76
    throw AppInstException(errno);
77
 
78
  return false;
79
}
80
 
81
bool AppInstance::Lock()
82
{
83
  for (int i=0; i<100; i++) {
71 luk 84
    if (DoLock())
69 luk 85
      return true;
86
 
71 luk 87
    FILE* f = fopen(m_path.c_str(), "r");
69 luk 88
    if (f == NULL) {
89
      if (errno != ENOENT)
90
        throw AppInstException(errno);
91
    }
92
    else {
93
      unsigned pid;
94
      ssize_t len = fscanf(f, "%u", &pid);
95
      if (len == -1) {
96
        AppInstException e(errno);
97
        fclose(f);
98
        throw e;
99
      }
100
      else if (len == 0) {
101
        AppInstException e(EIO);
102
        fclose(f);
103
        throw e;
104
      }
105
 
106
      fclose(f);
107
 
108
      int res = kill((pid_t) pid, 0);
109
      if (res == 0)
110
        return false;
111
 
112
      if (errno != ESRCH)
113
        throw AppInstException(errno);
114
 
71 luk 115
      res = unlink(m_path.c_str());
69 luk 116
      if (res != 0 && errno != ENOENT)
117
        throw AppInstException(errno);
118
    }
119
  }
120
 
121
  return false;
122
}
123
 
124
void AppInstance::Unlock()
125
{
126
  if (!m_fLocked)
127
    return;
128
 
71 luk 129
  if (unlink(m_path.c_str()) != 0 && errno != ENOENT)
69 luk 130
    throw AppInstException(errno);
131
 
132
  m_fLocked = false;
133
}
134
 
135
bool AppInstance::Exists() const
136
{
137
  if (m_fLocked)
138
    return true;
139
 
71 luk 140
  FILE* f = fopen(m_path.c_str(), "r");
69 luk 141
  if (f == NULL) {
142
    if (errno == ENOENT)
143
      return false;
144
    else
145
      throw AppInstException(errno);
146
  }
147
 
148
  bool ok = false;
149
 
150
  unsigned pid;
151
  if (fscanf(f, "%u", &pid) == 1) {
152
    if (kill((pid_t) pid, 0) == 0)
153
      ok = true;
154
    else if (errno != ESRCH) {
155
      AppInstException e(errno);
156
      fclose(f);
157
      throw e;
158
    }
159
  }
160
 
161
  fclose(f);
162
 
163
  return ok;
164
}
165
 
166
bool AppInstance::SendSignal(int iSigNo) const
167
{
71 luk 168
  FILE* f = fopen(m_path.c_str(), "r");
69 luk 169
  if (f == NULL) {
170
    if (errno == ENOENT)
171
      return false;
172
    else
173
      throw AppInstException(errno);
174
  }
175
 
176
  bool ok = false;
177
 
178
  unsigned pid;
179
  if (fscanf(f, "%u", &pid) == 1) {
180
    if (pid != (unsigned) getpid()) {
181
      if (kill((pid_t) pid, iSigNo) == 0) {
182
        ok = true;
183
      }
184
      else if (errno != ESRCH) {
185
        AppInstException e(errno);
186
        fclose(f);
187
        throw e;
188
      }
189
    }
190
  }
191
 
192
  fclose(f);
193
 
194
  return ok;
195
}
196