Home > Software design >  continue the execution of a function after handled panic
continue the execution of a function after handled panic

Time:05-11

I'm trying to make a task scheduler that does tasks in the given interval and also can handle an occurring panic. My question is how can I continue executing the function after handling the panic.

func scheduleTask(task func() error, interval time.Duration, timeout time.Duration) {
        //add waitgroup and mutex
        var wg sync.WaitGroup
        var mtx sync.Mutex
        var startTime = time.Now()
        //add each task to a goroutine and set interval and timeout to the function
        wg.Add(1)
        go func() {
            defer wg.Done()
            for {
                //check if the time is up
                if time.Since(startTime) > timeout {
                    break
                }
                defer func() {
                    if r := recover(); r != nil {
                        log.Println("Recovering from panic:", r)
                    }
                }()
                
                mtx.Lock()
                task()
                mtx.Unlock()

    
            }
        }()
        wg.Wait()
    }
    
    func main() {
        var a = 0
    
        scheduleTask(func() error {
            time.Sleep(50 * time.Millisecond)
            if a == 3 {
                a  
                panic("oops")
            }
            a  
            return nil
        }, time.Millisecond*100, time.Millisecond*1000)
    
        log.Println(a)
        if a != 10 {
            log.Fatal("Expected it to be 10")
        }
    }

CodePudding user response:

When recovering you will exit the current function. In this case you can easily wrap the task() in a closure.

package main

import (
    "log"
    "sync"
    "time"
)

func scheduleTask(task func() error, interval time.Duration, timeout time.Duration) {
    //add waitgroup and mutex
    var wg sync.WaitGroup
    var mtx sync.Mutex
    var startTime = time.Now()
    //add each task to a goroutine and set interval and timeout to the function
    wg.Add(1)
    go func() {
        defer wg.Done()
        for {
            //check if the time is up
            if time.Since(startTime) > timeout {
                break
            }

            mtx.Lock()
            func() {
                defer func() {
                    if r := recover(); r != nil {
                        log.Println("Recovering from panic:", r)
                    }
                }()

                task()
            }()
            mtx.Unlock()

        }
    }()
    wg.Wait()
}

func main() {
    var a = 0

    scheduleTask(func() error {
        time.Sleep(50 * time.Millisecond)
        if a == 3 {
            a  
            panic("oops")
        }
        a  
        return nil
    }, time.Millisecond*100, time.Millisecond*1000)

    log.Println(a)
    if a != 10 {
        log.Fatal("Expected it to be 10")
    }
}

Playground link

  •  Tags:  
  • go
  • Related