Semaphore overflow prevention
When you remove an item from the `JoinableQueue` without calling `JoinableQueue.task_done()`, and then process that item, a semaphore overflow exception might be thrown. This is caused when the semaphore used to count the number of unfinished tasks overflows.
def post_tasks_noncompliant(jobs, es_url):
    import multiprocessing
    import requests
    jobs = multiprocessing.JoinableQueue()
    while True:
        try:
            # Noncompliant: fails to call JoinableQueue.task_done()
            # for each task removed from the JoinableQueue.
            image, image_name, tag = jobs.get()
            formatted_es_url = es_url.format(image_name)
            files = {'file': image.content, 'tag': tag}
            r = requests.post(formatted_es_url, files=files)
        finally:
            print("Task Done!!")
def post_tasks_compliant(jobs, es_url):
    import multiprocessing
    import requests
    jobs = multiprocessing.JoinableQueue()
    while True:
        try:
            image, image_name, tag = jobs.get()
            formatted_es_url = es_url.format(image_name)
            files = {'file': image.content, 'tag': tag}
            r = requests.post(formatted_es_url, files=files)
        finally:
            # Compliant: calls JoinableQueue.task_done()
            # for each task removed from the JoinableQueue.
            jobs.task_done()