#!/bin/bash

func() {
	local start line in_loop dummy cmd count
	declare -a cmd
	declare -i count
	cmd=("$@")
	set -- /dev/fd/*
	start=$#
	count=0
	while read line; do
		count=$(($count + 1))
		if [[ -z $in_loop ]]; then
			set -- /dev/fd/*
			in_loop=$#
		fi
		# this leaks pipe descriptors
		read dummy < <(stat "$HOME")
		set -- /dev/fd/*
		# if the following complex if .. fi is removed, then bash will
		# never reap the leaked descriptor from the above <(stat) call.
		# If this loop is long, it'll eventually hit the built-in limit
		# of 1024, and hilarity ensues.
		if [[ $# -eq $in_loop ]]; then
			echo "No descriptor leak detected."
		elif [[ $# -gt $in_loop ]]; then
			echo "Warning, detected <(pipeline) descriptor leak"
			# this cleans up the leaks, because bash appears to only process
			# outstanding pipe signals when a sub-process is started.
			: | :
			set -- /dev/fd/*
			if [[ $# -eq $in_loop ]]; then
				echo "Closed inner <(stat) call"
			elif [[ $# -eq $(($in_loop - 1)) ]]; then
				echo "Closed inner <(stat) call, and outer <(echo)"
				in_loop=$#
			elif [[ $# -gt $in_loop ]]; then
				echo "Error, couldn't work around <(pipeline) descriptor leak"
			else
				echo "Unknown situation($#|$in_loop)!"
				exit
			fi
		elif [[ $# -eq $(($in_loop - 1)) ]]; then
			echo "No leak, and outer <(echo) is closed."
			in_loop=$#
		else
			echo "Unknown situation($#|$in_loop)!"
			exit
		fi
		if [[ $count -eq 3 ]]; then
			break
		fi
	done < <("${cmd[@]}")
	set -- /dev/fd/*
}

func seq 1 1000
