risor-io / risor

Fast and flexible scripting for Go developers and DevOps.
https://risor.io
Apache License 2.0
581 stars 24 forks source link

Possible hang in the parser #197

Closed edhemphill closed 4 months ago

edhemphill commented 4 months ago

The following incorrect risor code seems to hang the parser.

//print("test: " + SLACK_URL_POST_MESSAGE)
print("test: ")

func post_to_slack() {
//    url := SLACK_URL_POST_MESSAGE
    url := ""
    return fetch(url, {
        headers: {
            'Content-Type': 'application/json',
        },
        method: 'POST',
        data: {
            blocks: [
            {
                type: "section",
                text: {
                    type: "mrkdwn",
                    text: "Hello, this is a test.\n\n *Hi you have a new nothing:*",
                },
            },
            {
                type: "divider"
            },

        }
        // data: {
        //     text: 'Hello, world!',
        // },
    })
}

post_to_slack()

Note the lack of closing ] for blocks

Pardon the commented out stuff - left it in for context.

I found this while working on code using risor embedded, but it does hang on the CLI also.

MacOS 14.3 / go version go1.22.0 darwin/arm64

Here is a stack trace dumped via a kill SIGQUIT on risor compiling it:

 ~/go/bin/risor ~/ubuntu-work/publicweb-test/hula-config/test.risor

SIGQUIT: quit
PC=0x100f64764 m=0 sigcode=0

goroutine 1 gp=0x140000021c0 m=0 mp=0x109256420 [running]:
github.com/risor-io/risor/parser.(*Parser).nextToken(0x14000556fc8?)
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:175 +0x24 fp=0x14000905220 sp=0x14000904f20 pc=0x100f64764
github.com/risor-io/risor/parser.(*Parser).parseMapOrSet(0x14000556fc8)
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:1436 +0x8fc fp=0x14000905700 sp=0x14000905220 pc=0x100f7030c
github.com/risor-io/risor/parser.(*Parser).parseMapOrSet-fm()
    <autogenerated>:1 +0x28 fp=0x14000905720 sp=0x14000905700 pc=0x100f71f98
github.com/risor-io/risor/parser.(*Parser).parseNode(0x14000556fc8, 0x1)
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:483 +0xc8 fp=0x14000905880 sp=0x14000905720 pc=0x100f677e8
github.com/risor-io/risor/parser.(*Parser).parseExpression(0x14000556fc8, 0x1054cb583?)
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:503 +0x28 fp=0x140009059f0 sp=0x14000905880 pc=0x100f67a88
github.com/risor-io/risor/parser.(*Parser).parseKeyValue(0x14000556fc8)
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:1488 +0x6c fp=0x14000905a40 sp=0x140009059f0 pc=0x100f7050c
github.com/risor-io/risor/parser.(*Parser).parseMapOrSet(0x14000556fc8)
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:1426 +0x820 fp=0x14000905f20 sp=0x14000905a40 pc=0x100f70230
github.com/risor-io/risor/parser.(*Parser).parseMapOrSet-fm()
    <autogenerated>:1 +0x28 fp=0x14000905f40 sp=0x14000905f20 pc=0x100f71f98
github.com/risor-io/risor/parser.(*Parser).parseNode(0x14000556fc8, 0x1)
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:483 +0xc8 fp=0x140009060a0 sp=0x14000905f40 pc=0x100f677e8
github.com/risor-io/risor/parser.(*Parser).parseNodeList(0x14000556fc8, {0x105dd7a60, 0x1})
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:1240 +0x298 fp=0x14000906240 sp=0x140009060a0 pc=0x100f6e328
github.com/risor-io/risor/parser.(*Parser).parseCall(0x14000556fc8?, {0x106cf25a8?, 0x140007af7c0})
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:1319 +0x80 fp=0x140009064f0 sp=0x14000906240 pc=0x100f6ef70
github.com/risor-io/risor/parser.(*Parser).parseCall-fm({0x106cf25a8?, 0x140007af7c0?})
    <autogenerated>:1 +0x3c fp=0x14000906520 sp=0x140009064f0 pc=0x100f7253c
github.com/risor-io/risor/parser.(*Parser).parseNode(0x14000556fc8, 0x1)
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:493 +0x234 fp=0x14000906680 sp=0x14000906520 pc=0x100f67954
github.com/risor-io/risor/parser.(*Parser).parseExpression(0x14000556fc8, 0x100834f84?)
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:503 +0x28 fp=0x140009067f0 sp=0x14000906680 pc=0x100f67a88
github.com/risor-io/risor/parser.(*Parser).parseReturn(0x14000556fc8)
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:415 +0x178 fp=0x14000906d20 sp=0x140009067f0 pc=0x100f66d98
github.com/risor-io/risor/parser.(*Parser).parseStatement(0x14000556fc8?)
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:287 +0x1d4 fp=0x14000906d50 sp=0x14000906d20 pc=0x100f658d4
github.com/risor-io/risor/parser.(*Parser).parseBlock(0x14000556fc8)
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:983 +0xe8 fp=0x14000906f70 sp=0x14000906d50 pc=0x100f6c2b8
github.com/risor-io/risor/parser.(*Parser).parseFunc(0x14000556fc8)
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:1011 +0x194 fp=0x140009071a0 sp=0x14000906f70 pc=0x100f6c674
github.com/risor-io/risor/parser.(*Parser).parseFunc-fm()
    <autogenerated>:1 +0x28 fp=0x140009071c0 sp=0x140009071a0 pc=0x100f71d58
github.com/risor-io/risor/parser.(*Parser).parseNode(0x14000556fc8, 0x1)
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:483 +0xc8 fp=0x14000907320 sp=0x140009071c0 pc=0x100f677e8
github.com/risor-io/risor/parser.(*Parser).parseExpressionStatement(0x14000556fc8)
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:458 +0x2c fp=0x14000907490 sp=0x14000907320 pc=0x100f675dc
github.com/risor-io/risor/parser.(*Parser).parseStatement(0x14000556fc8?)
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:300 +0x230 fp=0x140009074c0 sp=0x14000907490 pc=0x100f65930
github.com/risor-io/risor/parser.(*Parser).Parse(0x14000556fc8, {0x106cf1a80, 0x1092bbe40})
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:215 +0x104 fp=0x14000907550 sp=0x140009074c0 pc=0x100f64d44
github.com/risor-io/risor/parser.Parse({0x106cf1a80, 0x1092bbe40}, {0x1400015a700?, 0x1008f714c?}, {0x0, 0x0, 0x0})
    /Users/edhemphill/ubuntu-work/risor/parser/parser.go:34 +0xa0 fp=0x14000907590 sp=0x14000907550 pc=0x100f625c0
github.com/risor-io/risor.Eval({0x106cf1a80, 0x1092bbe40}, {0x1400015a700, 0x32e}, {0x1400087cc00?, 0x400000000001be?, 0x151b90148?})
    /Users/edhemphill/ubuntu-work/risor/risor.go:19 +0x60 fp=0x140009075f0 sp=0x14000907590 pc=0x100fdc720
main.init.func2(0x109238a00, {0x140000c3360?, 0x4?, 0x1054bb753?})
    /Users/edhemphill/ubuntu-work/risor/cmd/risor/root.go:323 +0x1204 fp=0x14000907cc0 sp=0x140009075f0 pc=0x1054b7844
github.com/spf13/cobra.(*Command).execute(0x109238a00, {0x140000b20d0, 0x1, 0x1})
    /Users/edhemphill/go/pkg/mod/github.com/spf13/cobra@v1.7.0/command.go:944 +0x63c fp=0x14000907de0 sp=0x14000907cc0 pc=0x1009fc73c
github.com/spf13/cobra.(*Command).ExecuteC(0x109238a00)
    /Users/edhemphill/go/pkg/mod/github.com/spf13/cobra@v1.7.0/command.go:1068 +0x320 fp=0x14000907ea0 sp=0x14000907de0 pc=0x1009fcec0
github.com/spf13/cobra.(*Command).Execute(...)
    /Users/edhemphill/go/pkg/mod/github.com/spf13/cobra@v1.7.0/command.go:992
main.main()
    /Users/edhemphill/ubuntu-work/risor/cmd/risor/main.go:58 +0x1c4 fp=0x14000907f40 sp=0x14000907ea0 pc=0x1054b81c4
runtime.main()
    /usr/local/go/src/runtime/proc.go:271 +0x28c fp=0x14000907fd0 sp=0x14000907f40 pc=0x10085937c
runtime.goexit({})
    /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x14000907fd0 sp=0x14000907fd0 pc=0x10088f394

goroutine 2 gp=0x14000002c40 m=nil [force gc (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
    /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x140000eef90 sp=0x140000eef70 pc=0x1008597a8
runtime.goparkunlock(...)
    /usr/local/go/src/runtime/proc.go:408
runtime.forcegchelper()
    /usr/local/go/src/runtime/proc.go:326 +0xb8 fp=0x140000eefd0 sp=0x140000eef90 pc=0x100859638
runtime.goexit({})
    /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140000eefd0 sp=0x140000eefd0 pc=0x10088f394
created by runtime.init.6 in goroutine 1
    /usr/local/go/src/runtime/proc.go:314 +0x24

goroutine 3 gp=0x14000003500 m=nil [GC sweep wait]:
runtime.gopark(0x1?, 0x0?, 0x0?, 0x0?, 0x0?)
    /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x140000ef760 sp=0x140000ef740 pc=0x1008597a8
runtime.goparkunlock(...)
    /usr/local/go/src/runtime/proc.go:408
runtime.bgsweep(0x14000120000)
    /usr/local/go/src/runtime/mgcsweep.go:318 +0x108 fp=0x140000ef7b0 sp=0x140000ef760 pc=0x100845518
runtime.gcenable.gowrap1()
    /usr/local/go/src/runtime/mgc.go:203 +0x28 fp=0x140000ef7d0 sp=0x140000ef7b0 pc=0x1008396d8
runtime.goexit({})
    /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140000ef7d0 sp=0x140000ef7d0 pc=0x10088f394
created by runtime.gcenable in goroutine 1
    /usr/local/go/src/runtime/mgc.go:203 +0x6c

goroutine 4 gp=0x140000036c0 m=nil [GC scavenge wait]:
runtime.gopark(0x10000?, 0x105dd7968?, 0x0?, 0x0?, 0x0?)
    /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x140000eff60 sp=0x140000eff40 pc=0x1008597a8
runtime.goparkunlock(...)
    /usr/local/go/src/runtime/proc.go:408
runtime.(*scavengerState).park(0x109254000)
    /usr/local/go/src/runtime/mgcscavenge.go:425 +0x5c fp=0x140000eff90 sp=0x140000eff60 pc=0x100842eac
runtime.bgscavenge(0x14000120000)
    /usr/local/go/src/runtime/mgcscavenge.go:658 +0xac fp=0x140000effb0 sp=0x140000eff90 pc=0x10084346c
runtime.gcenable.gowrap2()
    /usr/local/go/src/runtime/mgc.go:204 +0x28 fp=0x140000effd0 sp=0x140000effb0 pc=0x100839678
runtime.goexit({})
    /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140000effd0 sp=0x140000effd0 pc=0x10088f394
created by runtime.gcenable in goroutine 1
    /usr/local/go/src/runtime/mgc.go:204 +0xac

goroutine 5 gp=0x14000003c00 m=nil [finalizer wait]:
runtime.gopark(0x140000ee618?, 0xa7?, 0x0?, 0x0?, 0x10086a818?)
    /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x140000ee580 sp=0x140000ee560 pc=0x1008597a8
runtime.runfinq()
    /usr/local/go/src/runtime/mfinal.go:194 +0x108 fp=0x140000ee7d0 sp=0x140000ee580 pc=0x1008387a8
runtime.goexit({})
    /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140000ee7d0 sp=0x140000ee7d0 pc=0x10088f394
created by runtime.createfing in goroutine 1
    /usr/local/go/src/runtime/mfinal.go:164 +0x80

goroutine 6 gp=0x14000003dc0 m=nil [sleep]:
runtime.gopark(0x7fb12de827f76?, 0x0?, 0x0?, 0x0?, 0x0?)
    /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x140000f0740 sp=0x140000f0720 pc=0x1008597a8
time.Sleep(0x6fc23ac00)
    /usr/local/go/src/runtime/time.go:195 +0xfc fp=0x140000f0780 sp=0x140000f0740 pc=0x10088bf2c
sigs.k8s.io/controller-runtime/pkg/log.init.0.func1()
    /Users/edhemphill/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.14.2/pkg/log/log.go:63 +0x30 fp=0x140000f07d0 sp=0x140000f0780 pc=0x105139790
runtime.goexit({})
    /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140000f07d0 sp=0x140000f07d0 pc=0x10088f394
created by sigs.k8s.io/controller-runtime/pkg/log.init.0 in goroutine 1
    /Users/edhemphill/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.14.2/pkg/log/log.go:62 +0x24

goroutine 18 gp=0x140003b7340 m=nil [GC worker (idle)]:
runtime.gopark(0x7fb12e11ba139?, 0x3?, 0xeb?, 0x21?, 0x0?)
    /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x140000ea730 sp=0x140000ea710 pc=0x1008597a8
runtime.gcBgMarkWorker()
    /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x140000ea7d0 sp=0x140000ea730 pc=0x10083b7c8
runtime.goexit({})
    /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140000ea7d0 sp=0x140000ea7d0 pc=0x10088f394
created by runtime.gcBgMarkStartWorkers in goroutine 1
    /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 7 gp=0x1400017e000 m=nil [GC worker (idle)]:
runtime.gopark(0x7fb12e11ba73f?, 0x3?, 0x68?, 0x42?, 0x0?)
    /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x140000f0f30 sp=0x140000f0f10 pc=0x1008597a8
runtime.gcBgMarkWorker()
    /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x140000f0fd0 sp=0x140000f0f30 pc=0x10083b7c8
runtime.goexit({})
    /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140000f0fd0 sp=0x140000f0fd0 pc=0x10088f394
created by runtime.gcBgMarkStartWorkers in goroutine 1
    /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 34 gp=0x14000184380 m=nil [GC worker (idle)]:
runtime.gopark(0x7fb12e119fe9b?, 0x0?, 0x0?, 0x0?, 0x0?)
    /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x1400019a730 sp=0x1400019a710 pc=0x1008597a8
runtime.gcBgMarkWorker()
    /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x1400019a7d0 sp=0x1400019a730 pc=0x10083b7c8
runtime.goexit({})
    /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x1400019a7d0 sp=0x1400019a7d0 pc=0x10088f394
created by runtime.gcBgMarkStartWorkers in goroutine 1
    /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 35 gp=0x14000184540 m=nil [GC worker (idle)]:
runtime.gopark(0x7fb12e11ba7e6?, 0x3?, 0xd9?, 0x52?, 0x0?)
    /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x1400019af30 sp=0x1400019af10 pc=0x1008597a8
runtime.gcBgMarkWorker()
    /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x1400019afd0 sp=0x1400019af30 pc=0x10083b7c8
runtime.goexit({})
    /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x1400019afd0 sp=0x1400019afd0 pc=0x10088f394
created by runtime.gcBgMarkStartWorkers in goroutine 1
    /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 36 gp=0x14000184700 m=nil [GC worker (idle)]:
runtime.gopark(0x7fb12e11a71d7?, 0x0?, 0x0?, 0x0?, 0x0?)
    /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x1400019b730 sp=0x1400019b710 pc=0x1008597a8
runtime.gcBgMarkWorker()
    /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x1400019b7d0 sp=0x1400019b730 pc=0x10083b7c8
runtime.goexit({})
    /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x1400019b7d0 sp=0x1400019b7d0 pc=0x10088f394
created by runtime.gcBgMarkStartWorkers in goroutine 1
    /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 19 gp=0x140003b7500 m=nil [GC worker (idle)]:
runtime.gopark(0x1092bdb20?, 0x1?, 0x82?, 0x3d?, 0x0?)
    /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x140000eaf30 sp=0x140000eaf10 pc=0x1008597a8
runtime.gcBgMarkWorker()
    /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x140000eafd0 sp=0x140000eaf30 pc=0x10083b7c8
runtime.goexit({})
    /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140000eafd0 sp=0x140000eafd0 pc=0x10088f394
created by runtime.gcBgMarkStartWorkers in goroutine 1
    /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 37 gp=0x140001848c0 m=nil [GC worker (idle)]:
runtime.gopark(0x7fb12e11ba7bc?, 0x1?, 0x1d?, 0xa?, 0x0?)
    /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x1400019bf30 sp=0x1400019bf10 pc=0x1008597a8
runtime.gcBgMarkWorker()
    /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x1400019bfd0 sp=0x1400019bf30 pc=0x10083b7c8
runtime.goexit({})
    /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x1400019bfd0 sp=0x1400019bfd0 pc=0x10088f394
created by runtime.gcBgMarkStartWorkers in goroutine 1
    /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 20 gp=0x140003b76c0 m=nil [GC worker (idle)]:
runtime.gopark(0x7fb12e11ba645?, 0x3?, 0x1e?, 0x6c?, 0x0?)
    /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x140000eb730 sp=0x140000eb710 pc=0x1008597a8
runtime.gcBgMarkWorker()
    /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x140000eb7d0 sp=0x140000eb730 pc=0x10083b7c8
runtime.goexit({})
    /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x140000eb7d0 sp=0x140000eb7d0 pc=0x10088f394
created by runtime.gcBgMarkStartWorkers in goroutine 1
    /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 38 gp=0x14000184a80 m=nil [GC worker (idle)]:
runtime.gopark(0x7fb12e11b507f?, 0x3?, 0xc9?, 0x24?, 0x0?)
    /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x1400019c730 sp=0x1400019c710 pc=0x1008597a8
runtime.gcBgMarkWorker()
    /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x1400019c7d0 sp=0x1400019c730 pc=0x10083b7c8
runtime.goexit({})
    /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x1400019c7d0 sp=0x1400019c7d0 pc=0x10088f394
created by runtime.gcBgMarkStartWorkers in goroutine 1
    /usr/local/go/src/runtime/mgc.go:1234 +0x28

goroutine 39 gp=0x14000184c40 m=nil [GC worker (idle)]:
runtime.gopark(0x1092bdb20?, 0x1?, 0xcb?, 0x77?, 0x0?)
    /usr/local/go/src/runtime/proc.go:402 +0xc8 fp=0x1400019cf30 sp=0x1400019cf10 pc=0x1008597a8
runtime.gcBgMarkWorker()
    /usr/local/go/src/runtime/mgc.go:1310 +0xd8 fp=0x1400019cfd0 sp=0x1400019cf30 pc=0x10083b7c8
runtime.goexit({})
    /usr/local/go/src/runtime/asm_arm64.s:1222 +0x4 fp=0x1400019cfd0 sp=0x1400019cfd0 pc=0x10088f394
created by runtime.gcBgMarkStartWorkers in goroutine 1
    /usr/local/go/src/runtime/mgc.go:1234 +0x28
edhemphill commented 4 months ago

Also of note, I can't seem to work around it by handing Parse() a context.WithTimeout - still hangs

edhemphill commented 4 months ago

Risor eating CPU during the hang, looks like 1 core:

77913  risor        87.8  00:20.03 13/1   0    34     28M    0B     0B     77913 41995 running  *0[1]

I tried --cpu-profile but since I have to interrupt via signal, it's producing a zero byte file.

edhemphill commented 4 months ago

OK fix --cpu-profile to write on SIGINT - here is the profile. parser_hang.zip

Also see: https://github.com/risor-io/risor/pull/198

myzie commented 4 months ago

Thank you @edhemphill. With all this info it shouldn’t be hard to track down and fix.

myzie commented 4 months ago

I whittled it down to this minimal case:

    { data: { blocks: [ { type: "divider" },    
        }
    }

Will work on the fix this weekend.