Skip to content

Commit

Permalink
Warn upon re-entrant call to Dream.sql (aantron#333)
Browse files Browse the repository at this point in the history
Resolves aantron#332.
  • Loading branch information
aantron authored Aug 21, 2024
1 parent 6081749 commit b0b401b
Showing 1 changed file with 19 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/sql/sql.ml
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,34 @@ let sql_pool ?size uri =
failwith message
end

(* In case a user calls Dream.sql within the callback of an outer call to
Dream.sql, if the database driver does not support concurrent database
connections, as with caqti-driver-sqlite3, the inner call to Dream.sql cannot
make progress and request handling deadlocks. This can occur when using SQL
sessions, a typical scenario. See
https://github.com/aantron/dream/issues/332. *)
let acquired_sql_connection : bool Lwt.key =
Lwt.new_key ()

let sql request callback =
match Message.field request pool_field with
| None ->
let message = "Dream.sql: no pool; did you apply Dream.sql_pool?" in
log.error (fun log -> log ~request "%s" message);
failwith message
| Some pool ->
begin match Lwt.get acquired_sql_connection with
| None | Some false -> ()
| Some true ->
let message =
"Re-entrant call to Dream.sql, perhaps through " ^
"Dream.set_session_field; could cause deadlock"
in
log.warning (fun log -> log ~request "%s" message)
end;
let%lwt result =
pool |> Caqti_lwt_unix.Pool.use (fun db ->
Lwt.with_value acquired_sql_connection (Some true) @@ fun () ->
(* The special exception handling is a workaround for
https://github.com/paurkedal/ocaml-caqti/issues/68. *)
match%lwt callback db with
Expand Down

0 comments on commit b0b401b

Please sign in to comment.