pidlock 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.mkd +24 -0
- data/lib/pidlock.rb +31 -0
- data/spec/lib/pidlock_spec.rb +70 -0
- data/spec/spec_helper.rb +8 -0
- metadata +60 -0
data/README.mkd
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Pidlock
|
2
|
+
|
3
|
+
[](http://travis-ci.org/abangratz/pidlock)
|
4
|
+
|
5
|
+
This is a ruby library for using pid-file based locking of programs/daemons to prevent multiple parallel running tasks.
|
6
|
+
|
7
|
+
## Prerequisites
|
8
|
+
|
9
|
+
The gem ``sys/proctable`` is required.
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
require 'sys/proctable'
|
15
|
+
|
16
|
+
Pidlock.new('my.pid').lock # tries to create a lock file '/var/run/my.pid';
|
17
|
+
# raises an error if the file is locked or a program exists that
|
18
|
+
# has the same basename and pid (here: 'my')
|
19
|
+
...
|
20
|
+
```
|
21
|
+
|
22
|
+
## TODO
|
23
|
+
|
24
|
+
Lots still. First release.
|
data/lib/pidlock.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
class Pidlock
|
2
|
+
|
3
|
+
|
4
|
+
class FileLockedException < Exception; end
|
5
|
+
class ProcessRunning < Exception; end
|
6
|
+
def initialize(name)
|
7
|
+
@name = File.basename(name)
|
8
|
+
@filename = File.join('/', 'var', 'run', @name)
|
9
|
+
end
|
10
|
+
|
11
|
+
def lock
|
12
|
+
unless @file
|
13
|
+
unless (File.writable?(File.dirname(@filename)))
|
14
|
+
@filename = File.join('/', 'tmp', @name)
|
15
|
+
end
|
16
|
+
@file = File.open(@filename, 'w+')
|
17
|
+
if (old_pid = @file.gets)
|
18
|
+
if (old_process = Sys::ProcTable.ps(old_pid.chomp.to_i))
|
19
|
+
raise ProcessRunning if old_process.comm == File.basename(@name, File.extname(@name))
|
20
|
+
else
|
21
|
+
STDERR.puts "WARNING: resetting stale lockfile"
|
22
|
+
@file.rewind
|
23
|
+
end
|
24
|
+
end
|
25
|
+
@file.flock(File::LOCK_EX | File::LOCK_NB) or raise FileLockedException
|
26
|
+
@file.write Process.pid
|
27
|
+
@file.flush
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Pidlock do
|
4
|
+
before(:each) do
|
5
|
+
@file = stub(File)
|
6
|
+
@file.stub(:flock)
|
7
|
+
@file.stub(:write)
|
8
|
+
@file.stub(:flock => 0)
|
9
|
+
@file.stub(:flush)
|
10
|
+
@file.stub(:gets)
|
11
|
+
File.stub(:open).with('/var/run/my.pid', 'w+').and_return(@file)
|
12
|
+
File.stub(:writable?).with('/var/run').and_return(true)
|
13
|
+
end
|
14
|
+
it "should create a file with the given name in /var/run" do
|
15
|
+
Pidlock.new('my.pid').lock
|
16
|
+
end
|
17
|
+
context "filehandling" do
|
18
|
+
before(:each) do
|
19
|
+
Process.stub(:pid).and_return(666)
|
20
|
+
end
|
21
|
+
it "should write the current pid to the file" do
|
22
|
+
@file.should_receive(:write).with(666)
|
23
|
+
Pidlock.new('my.pid').lock
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should try to lock the file" do
|
27
|
+
@file.should_receive(:flock).with( File::LOCK_EX | File::LOCK_NB).and_return(0)
|
28
|
+
Pidlock.new('my.pid').lock
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should raise if the lock does not succeed" do
|
32
|
+
@file.should_receive(:flock).with( File::LOCK_EX | File::LOCK_NB).and_return(false)
|
33
|
+
lambda {
|
34
|
+
Pidlock.new('my.pid').lock
|
35
|
+
}.should raise_error Pidlock::FileLockedException
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should check if the program name matches the id" do
|
39
|
+
@file.should_receive(:gets).and_return('666')
|
40
|
+
ps = stub("ProcTableStruct", :comm => 'test')
|
41
|
+
::Sys::ProcTable.should_receive(:ps).with(666).and_return(ps)
|
42
|
+
Pidlock.new('my.pid').lock
|
43
|
+
end
|
44
|
+
it "should raise if the program name does match the pid" do
|
45
|
+
@file.should_receive(:gets).and_return('666')
|
46
|
+
ps = stub("ProcTableStruct", :comm => 'my')
|
47
|
+
::Sys::ProcTable.should_receive(:ps).with(666).and_return(ps)
|
48
|
+
lambda {
|
49
|
+
Pidlock.new('my.pid').lock
|
50
|
+
}.should raise_error Pidlock::ProcessRunning
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should use /tmp if /var/run is not writeable" do
|
54
|
+
File.should_receive(:writable?).with('/var/run').and_return(false)
|
55
|
+
File.should_receive(:open).with('/tmp/my.pid', 'w+').and_return(@file)
|
56
|
+
Pidlock.new('my.pid').lock
|
57
|
+
|
58
|
+
end
|
59
|
+
it "should warn but continue if the file exists but the process name does not" do
|
60
|
+
@file.should_receive(:gets).and_return('667')
|
61
|
+
ps = stub("ProcTableStruct", :comm => 'test')
|
62
|
+
::Sys::ProcTable.should_receive(:ps).with(667).and_return(nil)
|
63
|
+
STDERR.should_receive(:puts).with('WARNING: resetting stale lockfile')
|
64
|
+
@file.should_receive(:rewind)
|
65
|
+
@file.should_receive(:write).with(666)
|
66
|
+
Pidlock.new('my.pid').lock
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pidlock
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Anton Bangratz
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-11-28 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: sys-proctable
|
16
|
+
requirement: &16613480 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.9.1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *16613480
|
25
|
+
description: Used for locking processes via PID and file (daemon style).
|
26
|
+
email: anton.bangratz@gmail.com
|
27
|
+
executables: []
|
28
|
+
extensions: []
|
29
|
+
extra_rdoc_files:
|
30
|
+
- README.mkd
|
31
|
+
files:
|
32
|
+
- lib/pidlock.rb
|
33
|
+
- spec/lib/pidlock_spec.rb
|
34
|
+
- spec/spec_helper.rb
|
35
|
+
- README.mkd
|
36
|
+
homepage: https://github.com/abangratz/pidlock
|
37
|
+
licenses: []
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
requirements: []
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 1.8.10
|
57
|
+
signing_key:
|
58
|
+
specification_version: 3
|
59
|
+
summary: Using PID/file locking for daemons and long running tasks made easy.
|
60
|
+
test_files: []
|