process_lock 0.0.1

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/.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