Skip to content

Commit 0bac3b1

Browse files
authored
Merge pull request #68 from paurkedal/issue67
Avoid possibly blocking calls to mysql_free_result.
2 parents b85e202 + 4c6d4e5 commit 0bac3b1

File tree

5 files changed

+60
-27
lines changed

5 files changed

+60
-27
lines changed

.github/workflows/workflow.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ jobs:
4848

4949
- name: Install system dependencies (ubuntu)
5050
if: "${{ matrix.os == 'ubuntu' }}"
51-
run: "apt-get update && apt-get install -y pkg-config libmariadb-dev"
51+
run: "apt-get update && apt-get install -y pkg-config libmariadb-dev libzstd-dev"
5252

5353
- name: Restore cached dependencies
5454
uses: actions/cache@v3

bindings/ffi_bindings.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,12 @@ module Functions (F : Ctypes.FOREIGN) = struct
346346

347347
(* Nonblocking API *)
348348

349+
let mysql_free_result_start = foreign "mysql_free_result_start"
350+
(res @-> returning int)
351+
352+
let mysql_free_result_cont = foreign "mysql_free_result_cont"
353+
(res @-> int @-> returning int)
354+
349355
let mysql_close_start = foreign "mysql_close_start"
350356
(mysql @-> returning int)
351357

lib/blocking.ml

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,23 @@ end
182182
module Stmt = struct
183183
type t = [`Blocking] Common.Stmt.t
184184

185+
let free_meta stmt =
186+
match stmt.Common.Stmt.meta with
187+
| None -> ()
188+
| Some { res; _ } ->
189+
stmt.meta <- None;
190+
B.mysql_free_result res
191+
192+
let free_meta_and_result stmt =
193+
match stmt.Common.Stmt.meta with
194+
| None -> true
195+
| Some { res; _ } ->
196+
stmt.meta <- None;
197+
B.mysql_free_result res;
198+
B.mysql_stmt_free_result stmt.Common.Stmt.raw
199+
185200
let execute stmt params =
201+
free_meta stmt;
186202
let n = B.mysql_stmt_param_count stmt.Common.Stmt.raw in
187203
if n <> Array.length params then
188204
Error (0, "parameter count mismatch")
@@ -200,21 +216,14 @@ module Stmt = struct
200216
| `Error e -> Error e
201217
end
202218

203-
let free_res stmt =
204-
if stmt.Common.Stmt.meta = None then true else
205-
begin
206-
Common.Stmt.free_meta stmt;
207-
B.mysql_stmt_free_result stmt.Common.Stmt.raw
208-
end
209-
210219
let reset stmt =
211-
if free_res stmt && B.mysql_stmt_reset stmt.Common.Stmt.raw then
220+
if free_meta_and_result stmt && B.mysql_stmt_reset stmt.Common.Stmt.raw then
212221
Ok ()
213222
else
214223
Error (Common.Stmt.error stmt)
215224

216225
let close stmt =
217-
if free_res stmt && B.mysql_stmt_close stmt.Common.Stmt.raw then
226+
if free_meta_and_result stmt && B.mysql_stmt_close stmt.Common.Stmt.raw then
218227
Ok ()
219228
else
220229
Error (Common.Stmt.error stmt)

lib/common.ml

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -375,15 +375,8 @@ module Stmt = struct
375375
b.Bind.buffers.(i) <- malloc n;
376376
setf (!@bp) T.Bind.buffer b.Bind.buffers.(i)
377377

378-
let free_meta stmt =
379-
match stmt.meta with
380-
| Some { res; _ } ->
381-
B.mysql_free_result res;
382-
stmt.meta <- None
383-
| None -> ()
384-
385378
let update_meta stmt =
386-
free_meta stmt;
379+
assert (stmt.meta = None);
387380
stmt.meta <- (
388381
match B.mysql_stmt_result_metadata stmt.raw with
389382
| Some res ->

lib/nonblocking.ml

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,19 @@ module Res = struct
252252

253253
let fetch (type t) (module R : Row.S with type t = t) res =
254254
(fetch_start (module R) res, fetch_cont (module R) res)
255+
256+
let handle_free = function
257+
| 0 -> `Ok
258+
| s -> `Wait (Status.of_int s)
259+
260+
let free_start res =
261+
handle_free (B.mysql_free_result_start res)
262+
263+
let free_cont res status =
264+
handle_free (B.mysql_free_result_cont res status)
265+
266+
let free res =
267+
(free_start res, free_cont res)
255268
end
256269

257270
module Stmt = struct
@@ -635,35 +648,47 @@ module Make (W : Wait) : S with type 'a future = 'a W.IO.future = struct
635648

636649
let insert_id =
637650
Res.insert_id
651+
652+
let free = (* not public, but to avoid shadowing *)
653+
Res.free
638654
end
639655

640656
module Stmt = struct
641657
type t = Stmt.t
642658

659+
let free_meta stmt =
660+
match stmt.Common.Stmt.meta with
661+
| None -> return ()
662+
| Some { res; _ } ->
663+
stmt.Common.Stmt.meta <- None;
664+
nonblocking' stmt.Common.Stmt.mariadb (Res.free res)
665+
666+
let free_meta_and_result stmt =
667+
match stmt.Common.Stmt.meta with
668+
| None -> return (Ok ())
669+
| Some { res; _ } ->
670+
stmt.Common.Stmt.meta <- None;
671+
nonblocking' stmt.Common.Stmt.mariadb (Res.free res) >>= fun () ->
672+
nonblocking stmt.Common.Stmt.mariadb (Stmt.free_result stmt)
673+
643674
let handle_execute = function
644675
| Ok stmt -> nonblocking stmt.Common.Stmt.mariadb (Stmt.store_result stmt)
645676
| Error _ as e -> return e
646677

647678
let execute stmt ps =
679+
free_meta stmt >>= fun () ->
648680
match Stmt.execute stmt ps with
649681
| `Ok nb -> nonblocking stmt.Common.Stmt.mariadb nb >>= handle_execute
650682
| `Error e -> return (Error e)
651683

652-
let free_res stmt =
653-
if stmt.Common.Stmt.meta = None then return (Ok ()) else
654-
begin
655-
Common.Stmt.free_meta stmt;
656-
nonblocking stmt.Common.Stmt.mariadb (Stmt.free_result stmt)
657-
end
658-
659684
let reset stmt =
660-
free_res stmt
685+
free_meta_and_result stmt
661686
>>= function
662687
| Ok () -> nonblocking stmt.Common.Stmt.mariadb (Stmt.reset stmt)
663688
| Error _ as e -> return e
664689

665690
let close stmt =
666-
free_res stmt
691+
free_meta_and_result stmt
667692
>>= function
668693
| Ok () -> nonblocking stmt.Common.Stmt.mariadb (Stmt.close stmt)
669694
| Error _ as e -> return e

0 commit comments

Comments
 (0)