pid_file_block 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b693b3fb17f115a6f52aeb7da5bf4ae85e33fc1ca73ad0da80706662eea145eb
4
+ data.tar.gz: 4247223843e8731087e4a01d3426cb8a26f87fe4897c302561fffc29e4e5e4d7
5
+ SHA512:
6
+ metadata.gz: fe77e37bff0d4b65182db0dbafa0d8744adc94d0baca392ed32a675bc4dfe1cc5631cbe8147a05370b73c0ea5044a5981bf33ae6ee141235530188986de9b818
7
+ data.tar.gz: 997dd255185343fd9a40a58a00bfb0d6a7e96cc71291ed112fca4efac3a9d042700ca58db9e16debd64eae4a954d8f3769291c2e0664eb287c7e5c2c29dc00cf
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ *~
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.5.1
7
+ before_install: gem install bundler -v 1.16.4
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in pid_file_block.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Alexander Kharitonov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # PidFileBlock
2
+
3
+ PidFileBlock - gem for easy use pid-files. The gem automatically creates and deletes pid-file for application.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'pid_file_block'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install pid_file_block
20
+
21
+ ## Usage
22
+
23
+ ### Simple example
24
+
25
+ ```ruby
26
+ #!/usr/bin/env ruby
27
+
28
+ require 'pid_file_block'
29
+
30
+ pid_file_block = PidFileBlock.new(piddir: '/run', pidfile: 'example.pid')
31
+ begin
32
+ pid_file_block.open do
33
+ # Put your code here
34
+ end
35
+ rescue PidFileBlock::ProcessExistsError
36
+ # Another process running. Exit with error.
37
+ exit 1
38
+ end
39
+ ```
40
+
41
+ ### With signal handlers
42
+
43
+ In previous example pid-file will not be deleted after the program termination with command kill or Ctrl-C. You may define your signal handlers and use the release method in them:
44
+
45
+ ```ruby
46
+ #!/usr/bin/env ruby
47
+
48
+ require 'pid_file_block'
49
+
50
+ $pid_file_block = nil
51
+
52
+ def do_exit
53
+ $pid_file_block.release if $pid_file_block
54
+ exit 0
55
+ end
56
+
57
+ old_term = Signal.trap('TERM') do
58
+ do_exit
59
+ end
60
+ old_int = Signal.trap('INT') do
61
+ do_exit
62
+ end
63
+
64
+ $pid_file_block = PidFileBlock.new(piddir: '/run', pidfile: 'example.run')
65
+ begin
66
+ $pid_file_block.open do
67
+ # Put your code here
68
+ end
69
+ rescue PidFileBlock::ProcessExistsError
70
+ # Another process running. Exit with error.
71
+ exit 1
72
+ end
73
+ ```
74
+
75
+ Another way - use the PidFileBlock::Application
76
+
77
+ ### PidFileBlock::Application
78
+
79
+ ```ruby
80
+ #!/usr/bin/env ruby
81
+
82
+ require 'pid_file_block'
83
+ require 'pid_file_block/application'
84
+
85
+ class MyApp < PidFileBlock::Application
86
+
87
+ def self.run_application
88
+ # Put your code here
89
+ end
90
+
91
+ end
92
+
93
+ MyApp.run(piddir: '/run', pidfile: 'example.pid')
94
+
95
+ ```
96
+
97
+ ## Contributing
98
+
99
+ Bug reports and pull requests are welcome on GitHub at https://github.com/askh/pid_file_block.
100
+
101
+ ## License
102
+
103
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "pid_file_block"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pid_file_block'
4
+
5
+ class PidFileBlock
6
+
7
+ class Application
8
+
9
+ def self.run_application
10
+ end
11
+
12
+ def self.do_exit(pid_file_block, exit_code)
13
+ pid_file_block.release if pid_file_block
14
+ exit exit_code
15
+ end
16
+
17
+ def self.run(piddir:,
18
+ pidfile:,
19
+ exit_code_normal: 0,
20
+ exit_code_process_exists_error: 1,
21
+ exit_code_interrupt: 2)
22
+ pid_file_block = nil
23
+ old_term = Signal.trap('TERM') do
24
+ do_exit(pid_file_block, exit_code_interrupt)
25
+ end
26
+ old_int = Signal.trap('INT') do
27
+ do_exit(pid_file_block, exit_code_interrupt)
28
+ end
29
+ pid_file_block = PidFileBlock.new(piddir: piddir, pidfile: pidfile)
30
+ begin
31
+ pid_file_block.open do
32
+ run_application
33
+ end
34
+ rescue PidFileBlock::ProcessExistsError
35
+ STDERR.puts "Error: process exists (see pid in file #{pid_file_block.pid_file_full_name})."
36
+ exit exit_code_process_exists_error
37
+ end
38
+ exit exit_code_normal
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+
@@ -0,0 +1,4 @@
1
+ class PidFileBlock
2
+ class ProcessExistsError < RuntimeError
3
+ end
4
+ end
@@ -0,0 +1,5 @@
1
+ class PidFileBlock
2
+ module Version
3
+ VERSION = "0.1.1".freeze
4
+ end
5
+ end
@@ -0,0 +1,95 @@
1
+ require 'pid_file_block/version'
2
+ require 'pid_file_block/process_exists_error'
3
+
4
+ class PidFileBlock
5
+
6
+ attr_reader :pid_file_full_name
7
+
8
+ def initialize(piddir: '/run', pidfile:)
9
+ pidfile ||= File.basename($0, '.*')
10
+ @pid_file_full_name = File.join(piddir, pidfile)
11
+ end
12
+
13
+ def open
14
+ loop do
15
+ begin
16
+ File.open(@pid_file_full_name, 'r') do |f|
17
+ f.flock(File::LOCK_EX)
18
+ if process_running?(f)
19
+ # f.flock(File::LOCK_UN)
20
+ raise PidFileBlock::ProcessExistsError
21
+ end
22
+ unlink_pid_file_if_exists
23
+ end
24
+ rescue Errno::ENOENT
25
+ end
26
+ begin
27
+ File.open(@pid_file_full_name,
28
+ File::Constants::RDWR|File::Constants::CREAT|File::Constants::EXCL) do |f|
29
+ f.flock(File::LOCK_EX)
30
+ if process_running?(f)
31
+ # f.flock(File::LOCK_UN)
32
+ raise PidFileBlock::ProcessExistsError
33
+ end
34
+ write_pid(f)
35
+ # f.flock(File::LOCK_UN)
36
+ end
37
+ break
38
+ rescue Errno::EEXIST
39
+ end
40
+ end
41
+ yield
42
+ unlink_pid_file_if_exists
43
+ end
44
+
45
+ def release
46
+ our_pid = $$
47
+ File.open(@pid_file_full_name, 'r') do |f|
48
+ f.flock(File::LOCK_EX)
49
+ file_pid_str = f.read
50
+ begin
51
+ file_pid = Integer(file_pid_str)
52
+ rescue ArgumentError
53
+ return false
54
+ end
55
+ if file_pid == our_pid
56
+ unlink_pid_file_if_exists
57
+ return true
58
+ else
59
+ return false
60
+ end
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def unlink_pid_file_if_exists
67
+ begin
68
+ File.unlink(@pid_file_full_name)
69
+ rescue Errno::ENOENT
70
+ end
71
+ end
72
+
73
+ def process_running?(file_handle)
74
+ file_handle.seek(0)
75
+ pid_str = file_handle.read
76
+ begin
77
+ pid = Integer(pid_str)
78
+ if Process.getpgid(pid)
79
+ return true
80
+ end
81
+ rescue Errno::ESRCH
82
+ return false
83
+ rescue ArgumentError
84
+ return false
85
+ end
86
+ raise 'Program Logic Error'
87
+ end
88
+
89
+ def write_pid(file_handle)
90
+ pid = $$
91
+ file_handle.truncate(0)
92
+ file_handle.write(pid)
93
+ end
94
+
95
+ end
@@ -0,0 +1,38 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "pid_file_block/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "pid_file_block"
8
+ spec.version = PidFileBlock::Version::VERSION
9
+ spec.authors = ["Alexander Kharitonov"]
10
+ spec.email = ["askh@askh.ru"]
11
+
12
+ spec.summary = %q{gem for easy use pid-file.}
13
+ spec.description = %q{gem for automatic checking, creation and deletion pid-file of an application.}
14
+ spec.homepage = "https://github.com/askh/pid_file_block"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ # if spec.respond_to?(:metadata)
20
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
21
+ # else
22
+ # raise "RubyGems 2.0 or newer is required to protect against " \
23
+ # "public gem pushes."
24
+ # end
25
+
26
+ # Specify which files should be added to the gem when it is released.
27
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
28
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
29
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
30
+ end
31
+ spec.bindir = "exe"
32
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
33
+ spec.require_paths = ["lib"]
34
+
35
+ spec.add_development_dependency "bundler", "~> 1.16"
36
+ spec.add_development_dependency "rake", "~> 10.0"
37
+ spec.add_development_dependency "minitest", "~> 5.0"
38
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pid_file_block
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Alexander Kharitonov
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-08-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ description: gem for automatic checking, creation and deletion pid-file of an application.
56
+ email:
57
+ - askh@askh.ru
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".travis.yml"
64
+ - Gemfile
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - bin/console
69
+ - bin/setup
70
+ - lib/pid_file_block.rb
71
+ - lib/pid_file_block/application.rb
72
+ - lib/pid_file_block/process_exists_error.rb
73
+ - lib/pid_file_block/version.rb
74
+ - pid_file_block.gemspec
75
+ homepage: https://github.com/askh/pid_file_block
76
+ licenses:
77
+ - MIT
78
+ metadata: {}
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 2.7.6
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: gem for easy use pid-file.
99
+ test_files: []