mattn / go-adodb

Microsoft ActiveX Object DataBase driver for go that using exp/sql
http://mattn.kaoriya.net/
MIT License
142 stars 36 forks source link

Query in HTTP Handler fails on 2nd request. #18

Open jbperry opened 9 years ago

jbperry commented 9 years ago

This reminds me a little bit of issue: https://github.com/mattn/go-adodb/issues/14

I've tried to reduce my code to the simplest form that can reproduce the problem. If I take my normal code to query a MS Access database and put it in an HttpHandler, it will always fail on the 2nd request to that path with "signal arrived during cgo execution". I can wait a minute or more between the 1st request (which will work) and the 2nd request (which will fail). I can also use a browser, curl, or wget to get the same results.

Yet I can call it repeatedly if I don't use it in a HttpHandler. I wonder if it has something to do with the http handler creating go routines?

I have GOARCH=386 as well, since I can't seem to make any queries work with Access unless I set that.

At this point, I've spent about a day of time trying various things and I'm running out of ideas.

    import (
        "database/sql"
        "fmt"
        _ "github.com/mattn/go-adodb"
        "net/http"
        "sync"
    )

    var mutex sync.Mutex

    func trendHandler(w http.ResponseWriter, r *http.Request) {
        mutex.Lock()
        defer mutex.Unlock()

        path := `C:\Alarm Frequency Report\BACtalk.mdb`
        connString := "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path + ";"
        db, err := sql.Open("adodb", connString)
        if err != nil {
            fmt.Println("Open", err)
            return
        }
        defer db.Close()

        rows, err := db.Query("SELECT devinst FROM tblAlarmHistory")
        if err != nil {
            fmt.Println("Query", err)
        }
        defer rows.Close()

        for rows.Next() {
            var id int
            rows.Scan(&id)
            fmt.Println(id)
        }
    }

    func main() {
        http.HandleFunc("/", trendHandler)
        http.ListenAndServe(":8080", nil)

        // 2nd request to url above always causes an error.
        // but, if you comment above and uncomment below
        // you can query to your hearts content.

        // for i := 0; i < 1000; i++ {
        //  trendHandler(nil, nil)
        // }
    }
jbperry commented 9 years ago

Here's an example of the error I get:

Exception 0xc00000fd 0x0 0x2372000 0x54907673 PC=0x54907673 signal arrived during cgo execution

github.com/mattn/go-ole.invoke(0x331fbdb8, 0x5, 0x1, 0x0, 0x0, 0x0, 0x127f6500, 0x0, 0x0) C:/code/go/src/github.com/mattn/go-ole/idispatch.go:199 +0x441 github.com/mattn/go-ole.(_IDispatch).Invoke(0x331fbdb8, 0x5, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0) C:/code/go/src/github.com/mattn/go-ole/idispatch.go:33 +0x62 github.com/mattn/go-ole/oleutil.CallMethod(0x331fbdb8, 0x628988, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0) C:/code/go/src/github.com/mattn/go-ole/oleutil/oleutil.go:53 +0x123 github.com/mattn/go-adodb.(_AdodbStmt).Query(0x127fa000, 0x75a890, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0) C:/code/go/src/github.com/mattn/go-adodb/adodb.go:197 +0xc5 database/sql.rowsiFromStatement(0x923230, 0x127b6de0, 0x923208, 0x127fa000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...) C:/Go/src/database/sql/sql.go:1489 +0x2b3 database/sql.(_DB).queryConn(0x127ba230, 0x127b6de0, 0x127d0c30, 0x663548, 0x23, 0x0, 0x0, 0x0, 0x127f5e60, 0x0, ...) C:/Go/src/database/sql/sql.go:978 +0x35d database/sql.(_DB).query(0x127ba230, 0x663548, 0x23, 0x0, 0x0, 0x0, 0x40f4e4, 0x0, 0x0) C:/Go/src/database/sql/sql.go:938 +0xe1 database/sql.(_DB).Query(0x127ba230, 0x663548, 0x23, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0) C:/Go/src/database/sql/sql.go:924 +0x83 main.trendHandler(0x923168, 0x127dc4d0, 0x127dc0e0) C:/code/go/src/trendGet2/main.go:26 +0x1fd net/http.HandlerFunc.ServeHTTP(0x69a50c, 0x923168, 0x127dc4d0, 0x127dc0e0) C:/Go/src/net/http/server.go:1265 +0x3b net/http.(_ServeMux).ServeHTTP(0x127b5d60, 0x923168, 0x127dc4d0, 0x127dc0e0) C:/Go/src/net/http/server.go:1541 +0x126 net/http.serverHandler.ServeHTTP(0x127b8440, 0x923168, 0x127dc4d0, 0x127dc0e0) C:/Go/src/net/http/server.go:1703 +0x145 net/http.(_conn).serve(0x127c0180) C:/Go/src/net/http/server.go:1204 +0x9d8 created by net/http.(_Server).Serve C:/Go/src/net/http/server.go:1751 +0x2ce

goroutine 1 [IO wait]: net.(_pollDesc).Wait(0x127da1b0, 0x72, 0x0, 0x0) C:/Go/src/net/fd_poll_runtime.go:84 +0x42 net.(_ioSrv).ExecIO(0x127d0308, 0x127da118, 0x62e498, 0x8, 0x127d0358, 0x127da7e0, 0x0, 0x0) C:/Go/src/net/fd_windows.go:188 +0x265 net.(_netFD).acceptOne(0x127da0e0, 0x127da700, 0x2, 0x2, 0x127da118, 0x69adb0, 0x0, 0x0) C:/Go/src/net/fd_windows.go:558 +0x3ee net.(_netFD).accept(0x127da0e0, 0x0, 0x0, 0x0) C:/Go/src/net/fd_windows.go:585 +0x119 net.(_TCPListener).AcceptTCP(0x127d0318, 0x127f9ed4, 0x0, 0x0) C:/Go/src/net/tcpsock_posix.go:234 +0x48 net/http.tcpKeepAliveListener.Accept(0x127d0318, 0x0, 0x0, 0x0, 0x0) C:/Go/src/net/http/server.go:1976 +0x48 net/http.(_Server).Serve(0x127b8440, 0x923060, 0x127d0318, 0x0, 0x0) C:/Go/src/net/http/server.go:1728 +0x7b net/http.(*Server).ListenAndServe(0x127b8440, 0x0, 0x0) C:/Go/src/net/http/server.go:1718 +0x101 net/http.ListenAndServe(0x627f78, 0x5, 0x0, 0x0, 0x0, 0x0) C:/Go/src/net/http/server.go:1808 +0x9e main.main() C:/code/go/src/trendGet2/main.go:41 +0x58

goroutine 6 [IO wait]: net.(_pollDesc).Wait(0x127da6f0, 0x72, 0x0, 0x0) C:/Go/src/net/fd_poll_runtime.go:84 +0x42 net.(_ioSrv).ExecIO(0x127d0308, 0x127da658, 0x62a048, 0x7, 0x69a578, 0x0, 0x0, 0x0) C:/Go/src/net/fd_windows.go:188 +0x265 net.(_netFD).Read(0x127da620, 0x12808000, 0x1000, 0x1000, 0x0, 0x0, 0x0) C:/Go/src/net/fd_windows.go:470 +0x11a net.(_conn).Read(0x127d0348, 0x12808000, 0x1000, 0x1000, 0x0, 0x0, 0x0) C:/Go/src/net/net.go:121 +0xba net/http.(_liveSwitchReader).Read(0x127c0204, 0x12808000, 0x1000, 0x1000, 0x0, 0x0, 0x0) C:/Go/src/net/http/server.go:214 +0x8b io.(_LimitedReader).Read(0x127b2bf0, 0x12808000, 0x1000, 0x1000, 0x910000, 0x0, 0x0) C:/Go/src/io/io.go:408 +0xda bufio.(_Reader).fill(0x127b65a0) C:/Go/src/bufio/bufio.go:97 +0x15c bufio.(_Reader).ReadSlice(0x127b65a0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0) C:/Go/src/bufio/bufio.go:295 +0x1ce bufio.(_Reader).ReadLine(0x127b65a0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0) C:/Go/src/bufio/bufio.go:324 +0x5a net/textproto.(_Reader).readLineSlice(0x127fa680, 0x0, 0x0, 0x0, 0x0, 0x0) C:/Go/src/net/textproto/reader.go:55 +0x76 net/textproto.(_Reader).ReadLine(0x127fa680, 0x0, 0x0, 0x0, 0x0) C:/Go/src/net/textproto/reader.go:36 +0x48 net/http.ReadRequest(0x127b65a0, 0x127dc2a0, 0x0, 0x0) C:/Go/src/net/http/request.go:598 +0xaf net/http.(_conn).readRequest(0x127c01e0, 0x0, 0x0, 0x0) C:/Go/src/net/http/server.go:586 +0x24b net/http.(_conn).serve(0x127c01e0) C:/Go/src/net/http/server.go:1162 +0x60f created by net/http.(_Server).Serve C:/Go/src/net/http/server.go:1751 +0x2ce

goroutine 8 [chan receive]: database/sql.(*DB).connectionOpener(0x127ba230) C:/Go/src/database/sql/sql.go:589 +0x43 created by database/sql.Open C:/Go/src/database/sql/sql.go:452 +0x256 eax 0x2372000 ebx 0x7fb ecx 0x236f054 edx 0xff edi 0x3304e690 esi 0x33994640 ebp 0x0 esp 0x238f440 eip 0x54907673 eflags 0x10206 cs 0x23 fs 0x53 gs 0x2b

jbperry commented 9 years ago

Any ideas what to try next? What could be going wrong? Thanks!

mattn commented 9 years ago

I'm looking this but this worked in older version of go.

takching commented 8 years ago

Should be the same issue as golang/go#9457 The workaround suggested there (adding blank import of "runtime/cgo") seems solve the problem.