Segmentation fault when using async pragma on generic procs #2377

Closed
jschweinsberg opened this Issue Mar 21, 2015 · 15 comments

Projects

None yet

7 participants

@jschweinsberg
Contributor

The compiler throws a segmentation fault during compilation of following test code:

import asyncdispatch

proc test[T](v: T) {.async.} =
  echo $v

asyncCheck test[int](1)
@jschweinsberg
Contributor

Traceback:

Traceback (most recent call last)
nim.nim(94)              nim
nim.nim(56)              handleCmdLine
main.nim(251)            mainCommand
main.nim(62)             commandCompileToC
modules.nim(203)         compileProject
modules.nim(151)         compileModule
passes.nim(197)          processModule
passes.nim(137)          processTopLevelStmt
sem.nim(446)             myProcess
sem.nim(420)             semStmtAndGenerateGenerics
semstmts.nim(1343)       semStmt
semexprs.nim(893)        semExprNoType
semexprs.nim(2206)       semExpr
semstmts.nim(1137)       semProc
semstmts.nim(956)        semProcAux
semstmts.nim(789)        semProcAnnotation
semstmts.nim(1343)       semStmt
semexprs.nim(893)        semExprNoType
semexprs.nim(2088)       semExpr
sem.nim(356)             semMacroExpr
sem.nim(329)             semAfterMacroCall
semstmts.nim(1343)       semStmt
semexprs.nim(893)        semExprNoType
semexprs.nim(2206)       semExpr
semstmts.nim(1137)       semProc
semstmts.nim(1083)       semProcAux
semgnrc.nim(403)         semGenericStmt
semgnrc.nim(398)         semGenericStmt
semgnrc.nim(388)         semGenericStmt
rodread.nim(899)         getBody
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
@dom96
Member
dom96 commented Mar 22, 2015

Interesting. The code that the async macro generates seems to work when input manually.

import asyncdispatch

template createCb(retFutureSym, iteratorNameSym,
                   name: expr): stmt {.immediate.} =
  var nameIterVar = iteratorNameSym
  {.push stackTrace: off.}
  proc cb {.closure,gcsafe.} =
    try:
      if not nameIterVar.finished:
        var next = nameIterVar()
        if next == nil:
          assert retFutureSym.finished, "Async procedure's (" &
                 name & ") return Future was not finished."
        else:
          next.callback = cb
    except:
      if retFutureSym.finished:
        # Take a look at tasyncexceptions for the bug which this fixes.
        # That test explains it better than I can here.
        raise
      else:
        echo(retFutureSym.repr)
        echo(getCurrentException().repr)
        retFutureSym.fail(getCurrentException())
  cb()
  {.pop.}

proc test[T](v: T): Future[void] =
  var retFuture = newFuture[void]("test")
  iterator testIter(): FutureBase {.closure.} =
    echo(v)
    complete(retFuture)
  createCb(retFuture, testIter, "test")
  return retFuture

asyncCheck test[int](1)
@dom96 dom96 added the Semcheck label Mar 22, 2015
@wiml
Contributor
wiml commented Apr 8, 2015

I just hit this as well; the smallest case I came up with is:

import asyncdispatch
proc doSomething[T]() {.async.} =
  discard
@dom96 dom96 added VM Generics labels May 17, 2015
@ephja
Contributor
ephja commented Jul 8, 2015

I've encountered this about 3 times now. Could this issue get tagged with a priority?

@Varriount
Contributor

My guess is that the async macro is messing up generic's AST structure.

@Araq Araq added Stdlib and removed Generics Semcheck VM labels Aug 9, 2015
@dom96 dom96 was assigned by Araq Aug 9, 2015
@Araq Araq added a commit that referenced this issue Aug 9, 2015
@Araq Araq refs #2377 bbf9757
@dom96
Member
dom96 commented Aug 24, 2015

@Araq Is this not a compiler issue?

@tulayang
Contributor

@dom96

I have the same trouble. And I found the problem in proc asyncSingleProc of asyncdispatch module:

var iteratorNameSym = genSym(nskIterator, $prc[0].getName & "Iter")  # Error

If I change into the following, it will be ok. I don't know why?

var iteratorNameSym = newIdentNode($prc[0].getName & "Iter")  # OK
@tulayang
Contributor

@dom96

And, this will be same error:

macro f(): stmt =
    result = newStmtList()
    var prc = newProc(name = genSym(nskProc, "myProc"), 
                      body = newCall("echo", newLit("OK")))
    result.add(prc)
    result.add(newCall("myProc"))

f()

This is ok:

macro f(): stmt =
    result = newStmtList()
    var prc = newProc(name = newIdentNode("myProc"), 
                      body = newCall("echo", newLit("OK")))
    result.add(prc)
    result.add(newCall("myProc"))

f()
@dom96
Member
dom96 commented Aug 31, 2015

Thank you for investigating. Pretty sure this is a compiler bug.

@dom96 dom96 added VM and removed Stdlib labels Aug 31, 2015
@Araq
Member
Araq commented Apr 3, 2016

Now fails with

temp.nim(12, 16) template/generic instantiation from here
temp.nim(10, 9) Error: implementation of 'testIter' expected

Which means it's no VM bug anymore. :-)

@Araq Araq added async and removed VM labels Apr 3, 2016
@dom96
Member
dom96 commented Apr 4, 2016

@Araq Still looks like a compiler bug though, I don't see anything wrong with the AST that my macro generates.

@Araq
Member
Araq commented Apr 4, 2016

Never said it's not a compiler bug. It's not a VM bug though.

@dom96
Member
dom96 commented Apr 4, 2016

Doesn't seem like it deserves the 'async' label then :)

@Araq
Member
Araq commented Apr 4, 2016

'async' doesn't mean dom's bug. :P

@Araq Araq assigned Araq and unassigned dom96 Apr 4, 2016
@Araq
Member
Araq commented Jul 8, 2016
macro f(): stmt =
    result = newStmtList()
    var prc = newProc(name = genSym(nskProc, "myProc"), 
                      body = newCall("echo", newLit("OK")))
    result.add(prc)
    result.add(newCall("myProc"))

f()

is not supposed to work. You have to keep the genSym in a local and re-use this local.

@Araq Araq added a commit that closed this issue Jul 8, 2016
@Araq Araq fixes #2377 1d186ee
@Araq Araq closed this in 1d186ee Jul 8, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment