pidlock 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.mkd ADDED
@@ -0,0 +1,24 @@
1
+ # Pidlock
2
+
3
+ [![Build Status](https://secure.travis-ci.org/abangratz/pidlock.png)](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
@@ -0,0 +1,8 @@
1
+ $: << '.'
2
+ require 'bundler/setup'
3
+ Bundler.setup(:default, :development)
4
+ require 'stringio'
5
+
6
+ require 'sys/proctable'
7
+ require 'lib/pidlock'
8
+
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: []