Subversion Repositories public

Rev

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