Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

error creating database (mongolite) connection in handler #205

Closed
ncullen93 opened this issue Nov 21, 2023 · 4 comments
Closed

error creating database (mongolite) connection in handler #205

ncullen93 opened this issue Nov 21, 2023 · 4 comments
Labels
bug not-confirmed not-confirmed bugreport

Comments

@ncullen93
Copy link

Creating a global mongolite db connection and then trying to grab records in a GET handler works the first time but then leads to a segfault error any subsequent requests. So, I tried to do the recommended thing of creating a db connection in each request. However, for mongo this leads to the following error:

objc[2671]: +[NSNumber initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.

Not sure if this is on mongolite's side, but it would be nice to at least see an example or hear from others who have made some kind of database solution work with RestRserve.

Basic reprex:

library(RestRserve)
library(mongolite)

fetch_models_handler <- function(req, res) {
  conn <- mongolite::mongo(collection, db, url)
 # then, eventually make a find() call and disconnect
 # adding conn$disconnect() doesnt help
}

app = Application$new(
  content_type = "application/json"
)

app$add_get(
  path = "/fetchModels",
  FUN = fetch_models_handler
)

backend = BackendRserve$new()
backend$start(app, http_port = 8080)
@ncullen93 ncullen93 added bug not-confirmed not-confirmed bugreport labels Nov 21, 2023
@ncullen93 ncullen93 changed the title error creating database (monglite) connection in handler error creating database (mongolite) connection in handler Nov 21, 2023
@ncullen93
Copy link
Author

ncullen93 commented Nov 21, 2023

Same segfault error when trying to create a DBI connection to a hosted database. It seems to work when the database is local, however.

Like adding using this to make a connection inside a handler causes a big segfault if it is not a local database:

  conn <- DBI::dbConnect(RPostgres::Postgres(),
                         host   ,
                         dbname,
                         user    ,
                         password,
                         port   )

Segfault looks like this:

 *** caught segfault ***
address 0x110, cause 'memory not mapped'

Traceback:
 1: connection_create(names(opts), as.vector(opts), check_interrupts)
 2: .local(drv, ...)
 3: DBI::dbConnect(RPostgres::Postgres(),  ...)
 4: DBI::dbConnect(RPostgres::Postgres(), ...)
 5: FUN(request, response)
 6: eval(quoted_code, env)
 7: eval(quoted_code, env)
 8: withCallingHandlers(eval(quoted_code, env), error = capture_calls)
 9: doTryCatch(return(expr), name, parentenv, handler)
10: tryCatchOne(expr, names, parentenv, handlers[[1L]])
11: tryCatchList(expr, classes, parentenv, handlers)
12: tryCatch(withCallingHandlers(eval(quoted_code, env), error = capture_calls),     error = identity)
13: try_capture_stack(expr)
14: private$eval_with_error_handling({    handler_id = private$match_handler(request, response)    FUN = private$handlers[[handler_id]]    self$logger$trace("", context = list(request_id = request$id,         message = sprintf("call handler '%s'", handler_id)))    FUN(request, response)})
15: eval(quoted_code, env)
16: eval(quoted_code, env)
17: withCallingHandlers(eval(quoted_code, env), error = capture_calls)
18: doTryCatch(return(expr), name, parentenv, handler)
19: tryCatchOne(expr, names, parentenv, handlers[[1L]])
20: tryCatchList(expr, classes, parentenv, handlers)
21: tryCatch(withCallingHandlers(eval(quoted_code, env), error = capture_calls),     error = identity)
22: try_capture_stack(expr)
23: private$eval_with_error_handling({    response$reset()    response$set_content_type(self$content_type)    self$logger$debug("", context = list(request_id = request$id,         request = list(method = request$method, path = request$path,             parameters_query = request$parameters_query, parameters_path = request$parameters_path,             headers = request$headers)))    mw_called = list()    mw_flag = "process_request"    need_call_handler = TRUE    for (id in seq_along(private$middleware)) {        mw_id = private$middleware[[id]][["id"]]        self$logger$trace("", context = list(request_id = request$id,             middleware = mw_id, message = sprintf("call %s middleware",                 mw_flag)))        FUN = private$middleware[[id]][[mw_flag]]        mw_status = private$eval_with_error_handling(FUN(request,             response))        mw_called[[id]] = id        if (!isTRUE(mw_status)) {            need_call_handler = FALSE            break        }    }    if (isTRUE(need_call_handler)) {        private$eval_with_error_handling({            handler_id = private$match_handler(request, response)            FUN = private$handlers[[handler_id]]            self$logger$trace("", context = list(request_id = request$id,                 message = sprintf("call handler '%s'", handler_id)))            FUN(request, response)        })    }    mw_flag = "process_response"    for (id in rev(mw_called)) {        mw_id = private$middleware[[id]][["id"]]        self$logger$trace("", context = list(request_id = request$id,             middleware = mw_id, message = sprintf("call %s middleware",                 mw_flag)))        FUN = private$middleware[[id]][[mw_flag]]        mw_status = private$eval_with_error_handling(FUN(request,             response))    }    self$logger$debug("", context = list(request_id = request$id,         response = list(status_code = response$status_code, headers = response$headers)))})
24: app$process_request()
25: self$convert_response(app$process_request())
26: .http.request("/fetchModels", NULL, NULL, as.raw(c(0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2d, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x3a, 0x20, 0x47, 0x45, 0x54, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x30, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x63, 0x75, 0x72, 0x6c, 0x2f, 0x37, 0x2e, 0x37, 0x37, 0x2e, 0x30, 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, 0x2a, 0x2f, 0x2a, 0x0a)))
27: doTryCatch(return(expr), name, parentenv, handler)
28: tryCatchOne(expr, names, parentenv, handlers[[1L]])
29: tryCatchList(expr, classes, parentenv, handlers)
30: tryCatch(expr, error = function(e) {    call <- conditionCall(e)    if (!is.null(call)) {        if (identical(call[[1L]], quote(doTryCatch)))             call <- sys.call(-4L)        dcall <- deparse(call, nlines = 1L)        prefix <- paste("Error in", dcall, ": ")        LONG <- 75L        sm <- strsplit(conditionMessage(e), "\n")[[1L]]        w <- 14L + nchar(dcall, type = "w") + nchar(sm[1L], type = "w")        if (is.na(w))             w <- 14L + nchar(dcall, type = "b") + nchar(sm[1L],                 type = "b")        if (w > LONG)             prefix <- paste0(prefix, "\n  ")    }    else prefix <- "Error : "    msg <- paste0(prefix, conditionMessage(e), "\n")    .Internal(seterrmessage(msg[1L]))    if (!silent && isTRUE(getOption("show.error.messages"))) {        cat(msg, file = outFile)        .Internal(printDeferredWarnings())    }    invisible(structure(msg, class = "try-error", condition = e))})
31: try(.http.request("/fetchModels", NULL, NULL, as.raw(c(0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2d, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x3a, 0x20, 0x47, 0x45, 0x54, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x38, 0x30, 0x38, 0x30, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x63, 0x75, 0x72, 0x6c, 0x2f, 0x37, 0x2e, 0x37, 0x37, 0x2e, 0x30, 0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, 0x2a, 0x2f, 0x2a, 0x0a))),     silent = TRUE)
32: (function (..., config.file = "/etc/Rserve.conf") {    if (is.null(run_Rserve))         stop("Runnig inside an embedded Rserve instance - starting Rserve recursively is not supported")    .Call(run_Rserve, as.character(config.file), sapply(list(...),         as.character))})(http.port = 8080, port = 6311)
33: do.call(Rserve::run.Rserve, ARGS)
34: backend$start(app)
An irrecoverable exception occurred. R is aborting now ...

@dselivanov
Copy link
Collaborator

dselivanov commented Nov 21, 2023 via email

@ncullen93
Copy link
Author

ncullen93 commented Nov 21, 2023

So weird... just deployed and it works perfectly find on heroku. Must be a local issue, but it's only with hosted databases. Sorry about that. I will close the issue and try to figure it out on my end.

@s-u
Copy link

s-u commented Nov 21, 2023

@ncullen93 the error suggests the you were running it on macOS in an interactive session - or that you included a package which tried to initialize interactive session/run-time. Please make sure the app is started via Rscript on the command line and not in any GUI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug not-confirmed not-confirmed bugreport
Projects
None yet
Development

No branches or pull requests

3 participants