Subversion Repositories public

Rev

Rev 108 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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