Subversion Repositories public

Rev

Rev 71 | Go to most recent revision | Details | 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
#ifdef APPINST_LOCK_DIRECTORY
30
#define LOCKDIR APPINST_LOCK_DIRECTORY
31
#else
32
#define LOCKDIR "/tmp"
33
#endif // APPINST_LOCK_DIRECTORY
34
 
35
 
36
 
37
AppInstance::AppInstance(const std::string& rName)
38
: m_name(rName),
39
  m_fLocked(false)
40
{
41
 
42
}
43
 
44
AppInstance::~AppInstance()
45
{
46
  try {
47
    Unlock();
48
  } catch (AppInstException e) {}
49
}
50
 
51
bool AppInstance::DoLock(const char* path)
52
{
53
  int fd = open(path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
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
  std::string fn = GetLockfile();
84
 
85
  for (int i=0; i<100; i++) {
86
    if (DoLock(fn.c_str()))
87
      return true;
88
 
89
    FILE* f = fopen(fn.c_str(), "r");
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
 
117
      res = unlink(fn.c_str());
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
 
131
  if (unlink(GetLockfile().c_str()) != 0 && errno != ENOENT)
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
 
142
  FILE* f = fopen(GetLockfile().c_str(), "r");
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
{
170
  FILE* f = fopen(GetLockfile().c_str(), "r");
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
 
199
std::string AppInstance::GetLockfile() const
200
{
201
  return std::string(LOCKDIR) + "/" + m_name + ".pid";
202
}