process_lock 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,46 @@
1
+ # Suggested by bundler
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+
20
+ ## RUBYMINE
21
+ .idea/
22
+
23
+ ## MAC OS
24
+ .DS_Store
25
+
26
+ ## TEXTMATE
27
+ *.tmproj
28
+ tmtags
29
+
30
+ ## EMACS
31
+ *~
32
+ \#*
33
+ .\#*
34
+
35
+ ## VIM
36
+ *.swp
37
+ *~
38
+
39
+ ## PROJECT::SPECIFIC
40
+ tmp/example*
41
+ ,*
42
+
43
+ # Local ruby version config
44
+ .rbenv-version
45
+ .ruby-version
46
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.travis.yml ADDED
@@ -0,0 +1,22 @@
1
+ language: ruby
2
+ # Just to override the --deployment default arg
3
+ bundler_args: --no-color
4
+ script: "bundle exec rake"
5
+
6
+ notifications:
7
+ email:
8
+ on_success: change
9
+ on_failure: always
10
+
11
+ rvm:
12
+ - 1.8.7
13
+ - 1.9.3
14
+ - 2.0.0
15
+ - 2.1.0
16
+ - jruby-19mode
17
+ - rbx
18
+
19
+ matrix:
20
+ allow_failures:
21
+ - rvm: rbx
22
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in process_lock.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,27 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ process_lock (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.2.5)
10
+ rake (10.1.1)
11
+ rspec (2.14.1)
12
+ rspec-core (~> 2.14.0)
13
+ rspec-expectations (~> 2.14.0)
14
+ rspec-mocks (~> 2.14.0)
15
+ rspec-core (2.14.7)
16
+ rspec-expectations (2.14.4)
17
+ diff-lcs (>= 1.1.3, < 2.0)
18
+ rspec-mocks (2.14.4)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ bundler (~> 1.3)
25
+ process_lock!
26
+ rake
27
+ rspec (~> 2.0)
data/README.md ADDED
@@ -0,0 +1,137 @@
1
+ # ProcessLock
2
+
3
+ A simple class to acquire and check process-id file based locks on a unix filesystem.
4
+
5
+ [![Build Status](https://travis-ci.org/ianheggie/ruby-process-lock.png?branch=master)](https://travis-ci.org/ianheggie/ruby-process-lock)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'process_lock'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install process_lock
20
+
21
+ ## Usage
22
+
23
+ Create an instance of ProcessLock with a filename as the lock.
24
+ You may have more than one lock per process.
25
+
26
+ Methods:
27
+ * acquire - Acquires a lock if it can. Returns true (or value of block if block is passed) if a lock was acquired, otherwise false.
28
+ * acquire! - Same as acquire except it throws an exception if a lock could not be obtained.
29
+ * release - Releases the lock if we are the owner. Returns true if the lock was released.
30
+ * release! - Same as release except it throws an exception if a lock was not released.
31
+ * filename - the filename passed when the instance was created
32
+ * read - the process id in the lock file, otherwise 0 (zero)
33
+
34
+ Note:
35
+ * locks don't stack - if we have already acquired the lock subsequent calls will reacquire the lock. releasing an already released lock will fail.
36
+
37
+ To acquire a lock, do some work and then release it:
38
+
39
+ pl = ProcessLock.new('tmp/name_of_lock.pid')
40
+
41
+ acquired = pl.acquire do
42
+ puts "Do some work!"
43
+ end
44
+ puts "Unable to obtain a lock" unless acquired
45
+
46
+ # OR
47
+
48
+ while ! pl.acquire
49
+ puts "Trying to acquire a lock"
50
+ sleep(1)
51
+ end
52
+ puts "Do some work!"
53
+ pl.release
54
+
55
+
56
+ Example:
57
+
58
+ irb - run first
59
+
60
+ >> require 'process_lock'
61
+ => true
62
+ >> Process.pid
63
+ => 16568
64
+ >> p = ProcessLock.new('tmp/example.tmp')
65
+ => #<ProcessLock:0x00000001489c10 @filename="tmp/example.tmp">
66
+ >> p.alive?
67
+ => false
68
+ >> p.owner?
69
+ => false
70
+ >> p.read
71
+ => 0
72
+
73
+ >> p.acquire!
74
+ => true
75
+
76
+ >> p.alive?
77
+ => true
78
+ >> p.owner?
79
+ => true
80
+ >> p.read
81
+ => 16568
82
+ >> sleep(10)
83
+ => 10
84
+ >> p.release!
85
+ => true
86
+ >> p.alive?
87
+ => false
88
+ >> p.owner?
89
+ => false
90
+ >> p.read
91
+ => 0
92
+
93
+ 2nd irb, run after first has acquired the lock
94
+
95
+ >> require 'process_lock'
96
+ => true
97
+ >> Process.pid
98
+ => 16569
99
+ >> q = ProcessLock.new('tmp/example.tmp')
100
+ => #<ProcessLock:0x000000026e4090 @filename="tmp/example.tmp">
101
+ >> q.alive?
102
+ => true
103
+ >> q.owner?
104
+ => false
105
+ >> q.read
106
+ => 16568
107
+
108
+ >> q.acquire!
109
+ ProcessLock::AlreadyLocked: Unable to acquire lock
110
+ from /home/ianh/Projects/Github/ruby-process-lock/lib/process_lock.rb:28:in `acquire!'
111
+ from (irb):7
112
+ from /home/ianh/.rbenv/versions/1.9.3-p484/bin/irb:12:in `<main>'
113
+
114
+ >> q.alive?
115
+ => true
116
+ >> q.owner?
117
+ => false
118
+ >> q.read
119
+ => 16568
120
+ >>
121
+
122
+ example.tmp will contain the pid of the running process
123
+
124
+ ## Contributing
125
+
126
+ 1. Fork it
127
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
128
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
129
+ 4. Push to the branch (`git push origin my-new-feature`)
130
+ 5. Create new Pull Request
131
+
132
+ ## License and contributions
133
+
134
+ * Based on work Copyright (c) 2008 Simon Engledew, released under the MIT license.
135
+ * Subsequent work by Ian Heggie: packaged into a gem, added tests and acquire method, fixed acquire so it didn't overwrite locks by other processes.
136
+ * See git log for other contributers
137
+
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new('spec')
6
+
7
+ # If you want to make this the default task
8
+ task :default => :spec
@@ -0,0 +1,3 @@
1
+ class ProcessLock
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,116 @@
1
+ require 'process_lock/version'
2
+ require 'fileutils'
3
+
4
+ class ProcessLock
5
+
6
+ attr_reader :filename
7
+
8
+ class AlreadyLocked < StandardError
9
+ end
10
+
11
+ class NotLocked < StandardError
12
+ end
13
+
14
+ def initialize(filename)
15
+ @filename = filename
16
+ FileUtils.touch(@filename)
17
+ end
18
+
19
+ def acquire!
20
+ result = acquired = acquire_without_block
21
+ if acquired and block_given?
22
+ begin
23
+ result = yield
24
+ ensure
25
+ release
26
+ end
27
+ end
28
+ raise(AlreadyLocked.new('Unable to acquire lock')) unless acquired
29
+ result
30
+ end
31
+
32
+ def acquire
33
+ result = acquire_without_block
34
+ if result and block_given?
35
+ begin
36
+ result = yield
37
+ ensure
38
+ release
39
+ end
40
+ end
41
+ result
42
+ end
43
+
44
+ def release!
45
+ unless release
46
+ raise NotLocked.new('Unable to release lock (probably did not own it)')
47
+ end
48
+ true
49
+ end
50
+
51
+ def release
52
+ acquired = false
53
+ open_and_lock do |f|
54
+ acquired = owner?
55
+ if acquired
56
+ f.truncate(f.write(''))
57
+ end
58
+ end
59
+ acquired
60
+ end
61
+
62
+ def alive?
63
+ pid = read
64
+ return pid > 0 ? Process.kill(0, pid) > 0 : false
65
+ rescue
66
+ return false
67
+ end
68
+
69
+ def owner?
70
+ pid = read
71
+ pid and pid > 0 and pid == Process.pid
72
+ end
73
+
74
+ def read
75
+ open_and_lock{|f| f.read.to_i}
76
+ end
77
+
78
+ private
79
+
80
+ def acquire_without_block
81
+ result = false
82
+ open_and_lock do |f|
83
+ result = owner? || ! alive?
84
+ if result
85
+ f.rewind
86
+ f.truncate(f.write(Process.pid))
87
+ end
88
+ end
89
+ result
90
+ end
91
+
92
+ def open_and_lock
93
+ old_locked_file = @locked_file
94
+ if @locked_file
95
+ @locked_file.rewind
96
+ return yield @locked_file
97
+ else
98
+ File.open(@filename, 'r+') do |f|
99
+ lock(f) do
100
+ @locked_file = f
101
+ return yield f
102
+ end
103
+ end
104
+ end
105
+ ensure
106
+ @locked_file = old_locked_file
107
+ end
108
+
109
+ def lock(file, blocking = true)
110
+ file.flock(blocking ? File::LOCK_EX : File::LOCK_EX | File::LOCK_NB)
111
+ return yield
112
+ ensure
113
+ file.flock(File::LOCK_UN)
114
+ end
115
+
116
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'process_lock/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "process_lock"
8
+ spec.version = ProcessLock::VERSION
9
+ spec.authors = ["Simon Engledew", "Ian Heggie"]
10
+ spec.email = ["ian@heggie.biz"]
11
+ spec.description = %q{A simple class to aquire and check process-id file based locks on a unix filesystem.}
12
+ spec.summary = %q{Use process lock to see if a process is already running or designate a master process when running concurrent applications.}
13
+ spec.homepage = "https://github.com/ianheggie/ruby-process-lock"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec", '~> 2.0'
24
+ end
@@ -0,0 +1,14 @@
1
+ #!/bin/bash
2
+ #
3
+ # For testing with jruby because it doesnt have fork
4
+ # and it was a pain getting the script right from ruby system call.
5
+
6
+ file=${1:-/dev/null}
7
+ secs=${2:-0}
8
+ (
9
+ sleep ${secs} <&- >&- 2>&- &
10
+ echo $! > "$file"
11
+ echo "Background process: sleep $secs & echo $! > $file"
12
+ ) &
13
+ wait
14
+ exit 0
@@ -0,0 +1,231 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ require 'fileutils'
4
+
5
+ describe 'ProcessLock' do
6
+
7
+ before(:all) do
8
+ FileUtils.mkdir_p('tmp')
9
+ FileUtils.rm_f Dir.glob('tmp/example*.tmp')
10
+ end
11
+
12
+ describe '#acquire' do
13
+
14
+ it 'should acquire a lock when called without a block' do
15
+ p = ProcessLock.new('tmp/example1.txt')
16
+ p.should_not be_owner
17
+ p.acquire.should be_true
18
+ p.should be_owner
19
+ p.should be_alive
20
+ p.release.should be_true
21
+ p.should_not be_owner
22
+ p.should_not be_alive
23
+ end
24
+
25
+ it 'should acquire a lock when called with a block and then release it' do
26
+ p = ProcessLock.new('tmp/example2.txt')
27
+ p.should_not be_owner
28
+ did_something = false
29
+ p.acquire do
30
+ did_something = true
31
+ p.should be_owner
32
+ p.should be_alive
33
+ 'value from block'
34
+ end.should == 'value from block'
35
+ did_something.should be_true
36
+ p.should_not be_owner
37
+ p.should_not be_alive
38
+ end
39
+
40
+ def acquire_and_then_return_block_value(pl)
41
+ pl.acquire do
42
+ @acquired_lock = true
43
+ pl.should be_owner
44
+ pl.should be_alive
45
+ return yield
46
+ end
47
+ end
48
+
49
+ it 'should acquire a lock when called with a block containing a return and then release it' do
50
+ p = ProcessLock.new('tmp/example3.txt')
51
+ p.should_not be_owner
52
+ acquire_and_then_return_block_value(p) do
53
+ 'value returned by block'
54
+ end.should == 'value returned by block'
55
+ p.should_not be_owner
56
+ p.should_not be_alive
57
+ end
58
+
59
+ it 'should not acquire a lock if some other process has the lock' do
60
+ fn = 'tmp/example4.txt'
61
+ system('bash spec/other_process.sh "%s" 100' % fn)
62
+ p = ProcessLock.new(fn)
63
+ 200.times do |i|
64
+ break if p.read > 0
65
+ sleep(0.5)
66
+ puts "waited #{i+1} times" if i > 2
67
+ end
68
+ pid = p.read
69
+ puts "+ps -fp %d" % pid
70
+ system "ps -fp %d" % pid
71
+ # other process should have acquired the lock
72
+ p.should_not be_owner
73
+ p.should be_alive
74
+ p.acquire.should be_false
75
+ p.should_not be_owner
76
+ p.should be_alive
77
+ # also try block
78
+ did_something = false
79
+ p.acquire do
80
+ did_something = true
81
+ 'Some value'
82
+ end.should be_false
83
+ did_something.should be_false
84
+ p.should_not be_owner
85
+ p.should be_alive
86
+ Process.kill(9, pid) if pid> 0
87
+ end
88
+
89
+ it 'should acquire a lock if an completed process has the lock' do
90
+ fn = 'tmp/example5.txt'
91
+ system('bash spec/other_process.sh "%s" 0' % fn)
92
+ p = ProcessLock.new(fn)
93
+ 200.times do |i|
94
+ break if p.read > 0 && ! p.alive?
95
+ sleep(0.5)
96
+ puts "waited #{i+1} times" if i > 2
97
+ end
98
+
99
+ p = ProcessLock.new(fn)
100
+ p.should_not be_owner
101
+ p.should_not be_alive
102
+ p.acquire.should be_true
103
+ p.should be_owner
104
+ p.should be_alive
105
+ p.release
106
+ end
107
+
108
+ it 'should allow multiple sequential locked sections' do
109
+ 3.times do
110
+ p = ProcessLock.new('tmp/example6.txt')
111
+ p.should_not be_owner
112
+ did_something = false
113
+ p.acquire do
114
+ did_something = true
115
+ p.should be_owner
116
+ p.should be_alive
117
+ end.should be_true
118
+ p.should_not be_owner
119
+ p.should_not be_alive
120
+ did_something.should be_true
121
+ end
122
+ end
123
+
124
+ it 'should allow multiple parallel but differently named locked sections' do
125
+ ps = 3.times.collect { |i| ProcessLock.new('tmp/example7-%d.txt' % i) }
126
+ did_something = 0
127
+ ps.each do |p|
128
+ p.should_not be_owner
129
+ p.acquire
130
+ p.should be_owner
131
+ p.should be_alive
132
+ end
133
+ ps.each do |p|
134
+ p.should be_owner
135
+ p.should be_alive
136
+ p.release
137
+ p.should_not be_owner
138
+ p.should_not be_alive
139
+ end
140
+ end
141
+
142
+ end
143
+
144
+ describe '#acquire!' do
145
+
146
+ it 'should call acquire and expect true' do
147
+ p = ProcessLock.new('tmp/example8.txt')
148
+ p.stub(:acquire_without_block).and_return(true)
149
+ p.acquire!.should be_true
150
+ end
151
+
152
+ it 'throw an error if acquire returns false' do
153
+ p = ProcessLock.new('tmp/example9.txt')
154
+ p.stub(:acquire_without_block).and_return(false)
155
+ expect { p.acquire! }.to raise_error(ProcessLock::AlreadyLocked)
156
+ end
157
+
158
+ it 'should acquire a lock when called with a block and then release it' do
159
+ p = ProcessLock.new('tmp/example2.txt')
160
+ p.should_not be_owner
161
+ did_something = false
162
+ p.acquire! do
163
+ did_something = true
164
+ p.should be_owner
165
+ p.should be_alive
166
+ 'some value'
167
+ end.should == 'some value'
168
+ did_something.should be_true
169
+ p.should_not be_owner
170
+ p.should_not be_alive
171
+ end
172
+
173
+ end
174
+
175
+ describe '#release!' do
176
+
177
+ it 'should call release and expect true' do
178
+ p = ProcessLock.new('tmp/example10.txt')
179
+ p.stub(:release).and_return(true)
180
+ p.release!.should be_true
181
+ end
182
+
183
+ it 'throw an error if release returns false' do
184
+ p = ProcessLock.new('tmp/example11.txt')
185
+ p.stub(:release).and_return(false)
186
+ expect { p.release! }.to raise_error(ProcessLock::NotLocked)
187
+ end
188
+ end
189
+
190
+
191
+ describe '#read' do
192
+
193
+ it 'should return the current PID if the lock was acquired' do
194
+ p = ProcessLock.new('tmp/example12.txt')
195
+ p.acquire do
196
+ p.read.should == Process.pid
197
+ p.should be_alive
198
+ end
199
+ p.should_not be_alive
200
+ end
201
+
202
+ it 'should return whatever number is in the file' do
203
+ p = ProcessLock.new('tmp/example13.txt')
204
+ File.open(p.filename, 'w') do |f|
205
+ f.puts('314152653')
206
+ end
207
+ p.read.should == 314152653
208
+ end
209
+
210
+ end
211
+
212
+ describe '#filename' do
213
+
214
+ it 'should return the filename' do
215
+ fn = 'tmp/example14.txt'
216
+ p = ProcessLock.new(fn)
217
+ p.filename.should == fn
218
+ end
219
+ end
220
+
221
+ it 'should use a string for the current PID in filename' do
222
+ p = ProcessLock.new('tmp/example15.txt')
223
+ p.acquire do
224
+ File.open(p.filename, 'r') do |f|
225
+ contents = f.read
226
+ contents.should == Process.pid.to_s
227
+ end
228
+ end
229
+ end
230
+
231
+ end
@@ -0,0 +1,404 @@
1
+ irb='irb -f --inspect -I lib --prompt simple '
2
+ rm -f tmp/example.tmp
3
+ set -x
4
+ (
5
+ $irb > ,irb1.out <<EOF
6
+ require 'process_lock'
7
+ Process.pid
8
+ p = ProcessLock.new('tmp/example.tmp')
9
+ p.alive?
10
+ p.owner?
11
+ p.read
12
+ p.acquire!
13
+ p.alive?
14
+ p.owner?
15
+ p.read
16
+ sleep(10)
17
+ p.release!
18
+ p.alive?
19
+ p.owner?
20
+ p.read
21
+ EOF
22
+ ) &
23
+
24
+ (
25
+ sleep 2
26
+ $irb <<EOF
27
+ require 'process_lock'
28
+ Process.pid
29
+ q = ProcessLock.new('tmp/example.tmp')
30
+ q.alive?
31
+ q.owner?
32
+ q.read
33
+ q.acquire!
34
+ q.alive?
35
+ q.owner?
36
+ q.read
37
+ EOF
38
+ ) | tee ,irb2.out
39
+
40
+ wait
41
+
42
+ exit
43
+
44
+ IRB1.9(1) General Commands Manual IRB1.9(1)
45
+
46
+
47
+
48
+ NAME
49
+ irb1.9.1 - interactive ruby
50
+
51
+ SYNOPSIS
52
+ irb [options]
53
+
54
+ DESCRIPTION
55
+ irb stands for `interactive ruby'. irb is a tool to execute interac‐
56
+ tively ruby expressions read from stdin. Use of irb is easy if you
57
+ know ruby. Executing irb, prompts are displayed as follows. Then,
58
+ enter expression of ruby. A input is executed when it is syntacticaly
59
+ completed.
60
+
61
+ $ irb1.9.1
62
+ irb(main):001:0> 1+2
63
+ 3
64
+ irb(main):002:0> class Foo
65
+ irb(main):003:1> def foo
66
+ irb(main):004:2> print 1
67
+ irb(main):005:2> end
68
+ irb(main):006:1> end
69
+ nil
70
+ irb(main):007:0>
71
+
72
+ And, Readline extesion module can be used with irb. Using Readline is
73
+ the standard default action if Readline is installed.
74
+
75
+ OPTIONS
76
+ -f suppress read ~/.irbrc
77
+
78
+ -m bc mode (fraction or matrix are available)
79
+
80
+ -d set $DEBUG to true (same as `ruby -d')
81
+
82
+ -r load-module
83
+ same as `ruby -r'
84
+
85
+ --inspect
86
+ uses `inspect' for output (the default except bc mode)
87
+
88
+ --noinspect
89
+ doesn't uses inspect for output
90
+
91
+ --readline
92
+ uses Readline extension module
93
+
94
+ --noreadline
95
+ doesn't use Readline extension module
96
+
97
+ --prompt prompt-mode
98
+
99
+ --prompt-mode prompt-mode
100
+ switches prompt mode. Pre-defined prompt modes are `default',
101
+ `simple', `xmp' and `inf-ruby'
102
+
103
+ --inf-ruby-mode
104
+ uses prompt appreciate for inf-ruby-mode on emacs. Suppresses
105
+ --readline.
106
+
107
+ --simple-prompt
108
+ simple prompt mode
109
+
110
+ --noprompt
111
+ no prompt
112
+
113
+ --tracer
114
+ display trace for each execution of commands.
115
+
116
+ --back-trace-limit n
117
+ displayes backtrace top n and tail n. The default value is 16.
118
+
119
+ --irb_debug n
120
+ sets internal debug level to n (It shouldn't be used)
121
+
122
+ -v, --version
123
+ prints the version of irb
124
+
125
+ CONFIGURATIONS
126
+ irb reads `~/.irbrc' when it is invoked. If `~/.irbrb' doesn't exist
127
+ irb try to read in the order `.irbrc', `irb.rc', `_irbrc' then
128
+ `$irbrc'. The following is altanative to the command line option. To
129
+ use them type as follows in an irb session.
130
+
131
+ IRB.conf[:IRB_NAME]="irb"
132
+ IRB.conf[:MATH_MODE]=false
133
+ IRB.conf[:USE_TRACER]=false
134
+ IRB.conf[:USE_LOADER]=false
135
+ IRB.conf[:IGNORE_SIGINT]=true
136
+ IRB.conf[:IGNORE_EOF]=false
137
+ IRB.conf[:INSPECT_MODE]=nil
138
+ IRB.conf[:IRB_RC] = nil
139
+ IRB.conf[:BACK_TRACE_LIMIT]=16
140
+ IRB.conf[:USE_LOADER] = false
141
+ IRB.conf[:USE_READLINE] = nil
142
+ IRB.conf[:USE_TRACER] = false
143
+ IRB.conf[:IGNORE_SIGINT] = true
144
+ IRB.conf[:IGNORE_EOF] = false
145
+ IRB.conf[:PROMPT_MODE] = :DEFALUT
146
+ IRB.conf[:PROMPT] = {...}
147
+ IRB.conf[:DEBUG_LEVEL]=0
148
+ IRB.conf[:VERBOSE]=true
149
+
150
+ Customizing prompt
151
+ To costomize the prompt you set a variable
152
+
153
+ IRB.conf[:PROMPT]
154
+
155
+ For example, describe as follows in `.irbrc'.
156
+
157
+ IRB.conf[:PROMPT][:MY_PROMPT] = { # name of prompt mode
158
+ :PROMPT_I => nil, # normal prompt
159
+ :PROMPT_S => nil, # prompt for continuated strings
160
+ :PROMPT_C => nil, # prompt for continuated statement
161
+ :RETURN => " ==>%s\n" # format to return value
162
+ }
163
+
164
+ Then, invoke irb with the above prompt mode by
165
+
166
+ $ irb1.9.1 --prompt my-prompt
167
+
168
+ Or add the following in `.irbrc'.
169
+
170
+ IRB.conf[:PROMPT_MODE] = :MY_PROMPT
171
+
172
+ Constants PROMPT_I, PROMPT_S and PROMPT_C specifies the format. In the
173
+ prompt specification, some special strings are available.
174
+
175
+ %N command name which is running
176
+ %m to_s of main object (self)
177
+ %M inspect of main object (self)
178
+ %l type of string(", ', /, ]), `]' is inner %w[...]
179
+ %NNi indent level. NN is degits and means as same as printf("%NNd").
180
+ It can be ommited
181
+ %NNn line number.
182
+ %% %
183
+ For instance, the default prompt mode is defined as follows:
184
+ IRB.conf[:PROMPT_MODE][:DEFAULT] = {
185
+
186
+ PROMPT_I => "%N(%m):%03n:%i> ",
187
+
188
+ PROMPT_S => "%N(%m):%03n:%i%l ",
189
+
190
+ PROMPT_C => "%N(%m):%03n:%i* ",
191
+
192
+ RETURN => "%s\n"}
193
+ RETURN is used to printf.
194
+
195
+ Configurating subirb
196
+ The command line option or IRB.conf specify the default behavior of
197
+ (sub)irb. On the other hand, each conf of in the next sction `6. Com‐
198
+ mand' is used to individually configurate (sub)irb. If proc is set to
199
+ IRB.conf[:IRB_RC], its subirb will be invoked after execution of that
200
+ proc under giving the context of irb as its aregument. By this mecha‐
201
+ nism each subirb can be configurated.
202
+
203
+ Command
204
+ For irb commands, both simple name and `irb_'-prefixed name are pre‐
205
+ pared.
206
+
207
+ exit, quit, irb_exit
208
+ Quits (sub)irb. if you've done cb (see below), exit from the
209
+ binding mode.
210
+
211
+
212
+ conf, irb_context
213
+ Displays current configuration. Modifing the configuration is
214
+ achieved by sending message to `conf'.
215
+
216
+ conf.back_trace_limit
217
+ Sets display lines of backtrace as top n and tail n. The
218
+ default value is 16.
219
+
220
+ conf.debug_level = N
221
+ Sets debug level of irb.
222
+
223
+ conf.ignore_eof = true/false
224
+ Whether ^D (control-d) will be ignored or not. If false is set,
225
+ ^D means quit.
226
+
227
+ conf.ignore_sigint= true/false
228
+ Whether ^C (control-c) will be ignored or not. If false is set,
229
+ ^D means quit. If true,
230
+ during input: cancel inputing then return to top level.
231
+ during execute: abondon current execution.
232
+
233
+ conf.inf_ruby_mode = true/false
234
+ Whether inf-ruby-mode or not. The default value is false.
235
+
236
+ conf.inspect_mode = true/false/nil
237
+ Specifies inspect mode. true: display inspect false: display
238
+ to_s nil: inspect mode in non math mode,
239
+ non inspect mode in math mode.
240
+
241
+ conf.irb_level
242
+ The level of cb.
243
+
244
+ conf.math_mode
245
+ Whether bc mode or not.
246
+
247
+ conf.use_loader = true/false
248
+ Whether irb's own file reader method is used when load/require
249
+ or not. This mode is globaly affected (irb wide).
250
+
251
+ conf.prompt_c
252
+ prompt for a continuating statement (e.g, immediately after of
253
+ `if')
254
+
255
+ conf.prompt_i
256
+ standard prompt
257
+
258
+ conf.prompt_s
259
+ prompt for a continuating string
260
+
261
+ conf.rc
262
+ Whether ~/.irbrc is read or not.
263
+
264
+ conf.use_prompt = true/false
265
+ Prompting or not.
266
+
267
+ conf.use_readline = true/false/nil
268
+ Whether readline is used or not. true: uses false: doen't use
269
+ nil: intends to use readline except for inf-reuby-mode (default)
270
+
271
+ conf.verbose=T/F
272
+ Whether verbose messages are display or not.
273
+
274
+ cb, irb_change_binding [obj]
275
+ Enter new binding which has a distinct scope of local variables.
276
+ If obj is given, obj will be self.
277
+
278
+ irb [obj]
279
+ Invoke subirb. If obj is given, obj will be self.
280
+
281
+ jobs, irb_jobs
282
+ List of subirb
283
+
284
+ fg n, irb_fg n
285
+ Switch into specified subirb. The following is candidates of n:
286
+ irb number
287
+ thhread
288
+ irb object
289
+ self(obj which is specified of irb obj)
290
+
291
+ kill n, irb_kill n
292
+ Kill subirb. The means of n is as same as the case of irb_fg.
293
+
294
+ System variable
295
+ _ The latest value of evaluation (it is local)
296
+
297
+ Session Example
298
+ $ irb1.9.1
299
+ irb(main):001:0> irb # invoke subirb
300
+ irb#1(main):001:0> jobs # list of subirbs
301
+ #0->irb on main (#<Thread:0x400fb7e4> : stop)
302
+ #1->irb#1 on main (#<Thread:0x40125d64> : running)
303
+ nil
304
+ irb#1(main):002:0> fg 0 # switch job
305
+ nil
306
+ irb(main):002:0> class Foo;end
307
+ nil
308
+ irb(main):003:0> irb Foo # invoke subirb which has the
309
+ # context of Foo
310
+ irb#2(Foo):001:0> def foo # define Foo#foo
311
+ irb#2(Foo):002:1> print 1
312
+ irb#2(Foo):003:1> end
313
+ nil
314
+ irb#2(Foo):004:0> fg 0 # switch job
315
+ nil
316
+ irb(main):004:0> jobs # list of job
317
+ #0->irb on main (#<Thread:0x400fb7e4> : running)
318
+ #1->irb#1 on main (#<Thread:0x40125d64> : stop)
319
+ #2->irb#2 on Foo (#<Thread:0x4011d54c> : stop)
320
+ nil
321
+ irb(main):005:0> Foo.instance_methods # Foo#foo is defined asurely
322
+ ["foo"]
323
+ irb(main):006:0> fg 2 # switch job
324
+ nil
325
+ irb#2(Foo):005:0> def bar # define Foo#bar
326
+ irb#2(Foo):006:1> print "bar"
327
+ irb#2(Foo):007:1> end
328
+ nil
329
+ irb#2(Foo):010:0> Foo.instance_methods
330
+ ["bar", "foo"]
331
+ irb#2(Foo):011:0> fg 0
332
+ nil
333
+ irb(main):007:0> f = Foo.new
334
+ #<Foo:0x4010af3c>
335
+ irb(main):008:0> irb f # invoke subirb which has the
336
+ # context of f (instance of Foo)
337
+ irb#3(#<Foo:0x4010af3c>):001:0> jobs
338
+ #0->irb on main (#<Thread:0x400fb7e4> : stop)
339
+ #1->irb#1 on main (#<Thread:0x40125d64> : stop)
340
+ #2->irb#2 on Foo (#<Thread:0x4011d54c> : stop)
341
+ #3->irb#3 on #<Foo:0x4010af3c> (#<Thread:0x4010a1e0> : running)
342
+ nil
343
+ irb#3(#<Foo:0x4010af3c>):002:0> foo # evaluate f.foo
344
+ 1nil
345
+ irb#3(#<Foo:0x4010af3c>):003:0> bar # evaluate f.bar
346
+ barnil
347
+ irb#3(#<Foo:0x4010af3c>):004:0> kill 1, 2, 3# kill job
348
+ nil
349
+ irb(main):009:0> jobs
350
+ #0->irb on main (#<Thread:0x400fb7e4> : running)
351
+ nil
352
+ irb(main):010:0> exit # exit
353
+
354
+ Restrictions
355
+ Because irb evaluates the inputs immediately after the imput is syntac‐
356
+ tically completed, irb gives slight different result than directly use
357
+ ruby. Known difference is pointed out here.
358
+
359
+ Declaration of the local variable
360
+ The following causes an error in ruby:
361
+
362
+ eval "foo = 0"
363
+ foo
364
+ --
365
+ -:2: undefined local variable or method `foo' for #<Object:0x40283118> (NameError)
366
+ ---
367
+ NameError
368
+
369
+ Though, the above will successfully done by irb.
370
+
371
+ >> eval "foo = 0"
372
+ => 0
373
+ >> foo
374
+ => 0
375
+
376
+ Ruby evaluates a code after reading entire of code and determination of
377
+ the scope of local variables. On the other hand, irb do immediately.
378
+ More precisely, irb evaluate at first
379
+
380
+ evel "foo = 0"
381
+
382
+ then foo is defined on this timing. It is because of this incompatibil‐
383
+ ity. If you'd like to detect those differences, begin...end can be
384
+ used:
385
+
386
+ >> begin
387
+ ?> eval "foo = 0"
388
+ >> foo
389
+ >> end
390
+ NameError: undefined local variable or method `foo' for #<Object:0x4013d0f0>
391
+ (irb):3
392
+ (irb_local_binding):1:in `eval'
393
+
394
+ Here-document
395
+ Implementation of Here-document is incomplete.
396
+
397
+ Symbol
398
+ Irb can not always recognize a symbol as to be Symbol. Concretely, an
399
+ expression have completed, however Irb regard it as continuation line.
400
+
401
+
402
+
403
+
404
+ December 2002 IRB1.9(1)
@@ -0,0 +1,20 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+
8
+ require 'process_lock'
9
+
10
+ RSpec.configure do |config|
11
+ config.treat_symbols_as_metadata_keys_with_true_values = true
12
+ config.run_all_when_everything_filtered = true
13
+ config.filter_run :focus
14
+
15
+ # Run specs in random order to surface order dependencies. If you find an
16
+ # order dependency and want to debug it, you can fix the order by providing
17
+ # the seed, which is printed after each run.
18
+ # --seed 1234
19
+ config.order = 'random'
20
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: process_lock
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Simon Engledew
9
+ - Ian Heggie
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2014-02-14 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: bundler
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '1.3'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: '1.3'
31
+ - !ruby/object:Gem::Dependency
32
+ name: rake
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: '2.0'
63
+ description: A simple class to aquire and check process-id file based locks on a unix
64
+ filesystem.
65
+ email:
66
+ - ian@heggie.biz
67
+ executables: []
68
+ extensions: []
69
+ extra_rdoc_files: []
70
+ files:
71
+ - .gitignore
72
+ - .rspec
73
+ - .travis.yml
74
+ - Gemfile
75
+ - Gemfile.lock
76
+ - README.md
77
+ - Rakefile
78
+ - lib/process_lock.rb
79
+ - lib/process_lock/version.rb
80
+ - process_lock.gemspec
81
+ - spec/other_process.sh
82
+ - spec/process_lock_spec.rb
83
+ - spec/run_example.sh
84
+ - spec/spec_helper.rb
85
+ homepage: https://github.com/ianheggie/ruby-process-lock
86
+ licenses:
87
+ - MIT
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 1.8.23
107
+ signing_key:
108
+ specification_version: 3
109
+ summary: Use process lock to see if a process is already running or designate a master
110
+ process when running concurrent applications.
111
+ test_files:
112
+ - spec/other_process.sh
113
+ - spec/process_lock_spec.rb
114
+ - spec/run_example.sh
115
+ - spec/spec_helper.rb