How to prevent a function from being called more than once

I have a combat system that I’m working on which involves players using quick and heavy attacks. I’ve encountered an issue wherein the attack function can be called twice if the player rapidly clicks the mouse, and is always called twice if the player holds the mouse button for a heavy attack. Here’s the relevant code snippets:

void Update()
{
    if(anim.GetCurrentAnimatorStateInfo(0).IsName("idle"))
    {
        isAttacking = false;
    }
    else
    {
        isAttacking = true;
    }

    if (!isAttacking)
    {
        // Right Attacks

        if ((Input.GetButton("Fire1")) && (Input.GetAxis("Horizontal") > 0))
        {
            holdTime++;
            if (holdTime >= 10)
            {
                StartCoroutine(rightHook());
                holdTime = 0;
            }
        }

        if ((Input.GetButtonUp("Fire1")) && (Input.GetAxis("Horizontal") > 0) && holdTime < 10)
        {
            StartCoroutine(rightJab());
            holdTime = 0;
        }

// Player Combat Functions

IEnumerator rightHook()
{
    anim.SetTrigger("rightHook");
    applyDamage(heavyDamage);
    debugCall++;
    Debug.Log("Function called: " + debugCall + " times.");
    yield break;
}

With the debug log you can see above, it counts twice. This is an issue, because it means damage is applied twice, and the animation is also triggered twice which looks bad. I thought an easy, clean way to determine whether or not the player was attacking was to check if they were in their idle animation (I’d have to change it later, but at the moment there’s no walking animations or anything else outside of the combat system). I’m guessing I’ll have to figure out a more intuitive way to return the isAttacking condition, but I’m at a loss. Any help would be greatly appreciated!

Your code looks fine. It would be running when again Holdtime become 10. I tried code same like you. Working perfectly fine. but its calling again and again when timer value equals to 10.

float timer = 0;
void Update()
{
    if ((Input.GetButton("Fire1")) && (Input.GetAxis("Horizontal") > 0))
    {
        timer += 1; if (timer >= 10)
        {
            StartCoroutine(print());
            timer = 0;
        }
    }
}

IEnumerator print()
{
    print("print times ");
    yield break;
}

i think this can help to execute the function only when it execute all tasks.

bool wait =false;

public void attack(){

if(wait==false){
wait=true;
//do something
//do something
//do something
wait=false;
}

}