亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

runtime/cgo: pthread_create failed: 資源暫時不可用

runtime/cgo: pthread_create failed: 資源暫時不可用

Go
一只甜甜圈 2022-05-10 17:15:02
我目前有這個功能,通過 ffmpeg 管道傳輸多個 youtubedl 命令,然后將 ffmpeg 的輸出管道傳輸到 HTTP 客戶端。func pipeThruFfmpegToMp4(vi *VideoInfo, rw web.ResponseWriter) error {    var ffmpeg *exec.Cmd    ffmpeg = exec.Command(        "ffmpeg",        "-i", "-",        "-i", "pipe:3",        "-c:v", "copy", "-c:a", "copy",        "-preset", "veryfast",        "-metadata", fmt.Sprintf(`title=%s`, vi.GetTitle()),        "-movflags", "frag_keyframe+empty_moov",        "-f", "mp4",        "-")    youtubevideo := exec.Command(YoutubeDLPath, "-c", "-f", fmt.Sprintf("%s/bestvideo[ext=mp4]/bestvideo/best", vi.GetFormat()), "--no-cache-dir", "--restrict-filenames", "--hls-prefer-native", "-o", "-", fmt.Sprintf("%s", vi.GetVideoUrl()))    fmt.Println(youtubevideo)    youtube := exec.Command(YoutubeDLPath, "-c", "-f", "bestaudio[ext=m4a]/bestaudio/best", "--no-cache-dir", "--restrict-filenames", "--hls-prefer-native", "-o", "-", fmt.Sprintf("%s", vi.GetVideoUrl()))    fmt.Println(youtube)    var ytvbuf, ytbuf, ffbuf bytes.Buffer    youtubevideo.Stderr = &ytvbuf    youtube.Stderr = &ytbuf    ffmpeg.Stderr = &ffbuf    video, err := youtubevideo.StdoutPipe()    if err != nil {        log.Printf("pipeThruFfmpegToMp4: %v\n", err)        return err    }    pipe3, err := youtube.StdoutPipe()    if err != nil {        log.Printf("pipeThruFfmpegToMp4: %v\n", err)        return err    }    ffmpeg.Stdin = video    ffmpeg.ExtraFiles = []*os.File{pipe3.(*os.File)}    ffmpeg.Stdout = rw    // Headers sent, no turning back now    rw.Header().Set("Content-Type", "video/mp4")    rw.Header().Set("Content-Disposition", fmt.Sprintf("attachment;filename=\"%s.mp4\"", vi.GetSlug()))    rw.Flush()    ffmpeg.Start()    youtubevideo.Start()    youtube.Start()    ffmpeg.Wait()    youtubevideo.Wait()    youtube.Wait()問題是一切運行正常,但過了一會兒,內存開始填滿服務器,直到它出現錯誤runtime/cgo: pthread_create failed: Resource temporarily unavailable我不確定這是否是內存泄漏,或者 youtube-dl 的任一實例是否未正確關閉,或者 ffmpeg 是否未正確關閉并且隨著程序運行更多而消耗越來越多的內存,直到程序因此錯誤而崩潰
查看完整描述

2 回答

?
慕標琳琳

TA貢獻1830條經驗 獲得超9個贊

我有時會遇到問題,您的代碼不會終止youtube-dl進程。視頻被轉換,但過程被保留。作為第一個指標,觀察進程計數,如下所示:


ps | grep youtube-dl | wc -l

可以讓子進程超時,對于一個子進程,這看起來像這樣:


package main


import (

    "bytes"

    "fmt"

    "os/exec"

    "time"

)


func main() {

    // Sleep is used, so we can control how long it runs.

    cmd := exec.Command("sleep", "2")


    // Use a bytes.Buffer to get the output

    var buf bytes.Buffer

    cmd.Stdout = &buf


    cmd.Start()


    // Use a channel to signal completion so we can use a select statement

    done := make(chan error)

    go func() { done <- cmd.Wait() }()


    // Start a timer, should be higher for your video conversion, 

    // I suggest you use a value that fits both your videos and server capabilities

    timeout := time.After(2 * time.Second)


    // The select statement allows us to execute based on which channel

    // we get a message from first.

    select {

    case <-timeout:

        // Timeout happened first, kill the process and print a message.

        cmd.Process.Kill()

        fmt.Println("Command timed out")

    case err := <-done:

        // Command completed before timeout. Print output and error if it exists.

        fmt.Println("Output:", buf.String())

        if err != nil {

            fmt.Println("Non-zero exit code:", err)

        }

    }

}

在你的情況下,你可以更換


    ffmpeg.Start()

    youtubevideo.Start()

    youtube.Start()

    ffmpeg.Wait()

    youtubevideo.Wait()

    youtube.Wait()


    ffmpeg.Start()

    youtubevideo.Start()

    youtube.Start()

    commands := 3


    done := make(chan error)

    go func() { done <- ffmpeg.Wait() }()

    go func() { done <- youtubevideo.Wait() }()

    go func() { done <- youtube.Wait() }()


    timeout := time.After(1 * time.Hour)


Loop:

    for {

        select {

        case <-timeout:

            ffmpeg.Process.Kill()

            youtubevideo.Process.Kill()

            youtube.Process.Kill()

            log.Println("Conversion timed out")

            break Loop

        case err := <-done:

            if err != nil {

                log.Println("Non-zero exit code:", err)

            }

            commands = commands - 1

            if commands == 0 {

                break Loop

            }

        }

    }


查看完整回答
反對 回復 2022-05-10
?
富國滬深

TA貢獻1790條經驗 獲得超9個贊

因此,經過一些調試并在凱文的回答的幫助下。成功后好像youtube-dl沒有關閉。


鑒于如果ffmpeg完成,那么讓youtube-dl實例運行沒有任何意義,并且由于Wait()函數正在等待youtube-dl完成,但它似乎從未發送完成信號,所以我繼續并不得不添加一個 kill 來殺死子子進程。


所以我不得不添加改變這個


    ffmpeg.Start()

    youtubevideo.Start()

    youtube.Start()

    ffmpeg.Wait()

    youtubevideo.Wait()

    youtube.Wait()

對此


    youtube.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}

    youtubevideo.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}

    ffmpeg.Start()

    youtubevideo.Start()

    youtube.Start()

    ffmpeg.Wait()

    syscall.Kill(-youtube.Process.Pid, syscall.SIGKILL)

    syscall.Kill(-youtubevideo.Process.Pid, syscall.SIGKILL)

    youtubevideo.Wait()

    youtube.Wait()

請注意,因為它似乎產生了某種子子youtube.Process.Kill()進程,實際上并沒有殺死該進程,這就是我必須使用的原因syscall,而且Setpgid: true


查看完整回答
反對 回復 2022-05-10
  • 2 回答
  • 0 關注
  • 1153 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號