Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use atomic mkdir rather than pidof #21

Open
raphaelcohn opened this issue Jun 4, 2021 · 0 comments
Open

Use atomic mkdir rather than pidof #21

raphaelcohn opened this issue Jun 4, 2021 · 0 comments

Comments

@raphaelcohn
Copy link

mkdir -m 0700 folder is atomic (with -p it is not).

Thus one can use it to make singleton instances of processes, eg:-

singleton_instance_lock()
{
local temporary_folder_path=...
local program_name=...
	single_instance_lock_folder_path=''

	local potential_single_instance_lock_folder_path="$temporary_folder_path"/"$program_name"
	local lock_holder_pid_file_path="$potential_single_instance_lock_folder_path"/lock_holder.pid
	local loop_count=0
	
	local exit_code
	while true
	do
		set +e
			mkdir -m 0700 "$potential_single_instance_lock_folder_path" 1>/dev/null 2>/dev/null
			exit_code=$?
		set -e
		
		if [ $exit_code -eq 0 ]; then
			printf '%s\n' $$ >"$lock_holder_pid_file_path"
			single_instance_lock_folder_path="$potential_single_instance_lock_folder_path"
			break
		fi
		
		local loop_division=$((loop_count % 5))
		if [ $loop_division -eq 0 ]; then
			local lock_holder_pid=''
			set +e
# Uses cat rather than $(<X) as the later echos failures to stderr irrespective.
				lock_holder_pid="$(cat "$lock_holder_pid_file_path" 2>/dev/null)"
			set -e
			
			if [ -z "$lock_holder_pid" ]; then
				lock_holder_pid='(unknown)'
			fi
			
			printf '%s:%s\n' "$_program_name" "Still waiting for single instance lock $potential_single_instance_lock_folder_path held by process $lock_holder_pid"
		fi
		loop_count=$((loop_count + 1))
		
		# Non-portable fractional sleep
		set +e
			sleep 0.1 1>/dev/null 2>/dev/null
			exit_code=$?
		set -e
		
		if [ $exit_code -ne 0 ]; then
			sleep 1 1>/dev/null 2>/dev/null
		fi
		
	done
	
	remove_single_instance_lock_folder_path()
	{
		if [ -n "$single_instance_lock_folder_path" ]; then
			rm -rf "$single_instance_lock_folder_path"
			single_instance_lock_folder_path=''
		fi
	}
	
	trap remove_single_instance_lock_folder_path EXIT
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant