exitprocs.nim 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2020 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## This module allows adding hooks to program exit.
  10. import locks
  11. when defined(js) and not defined(nodejs):
  12. import std/assertions
  13. type
  14. FunKind = enum kClosure, kNoconv # extend as needed
  15. Fun = object
  16. case kind: FunKind
  17. of kClosure: fun1: proc () {.closure.}
  18. of kNoconv: fun2: proc () {.noconv.}
  19. var
  20. gFunsLock: Lock
  21. gFuns: seq[Fun]
  22. initLock(gFunsLock)
  23. when defined(js):
  24. proc addAtExit(quitProc: proc() {.noconv.}) =
  25. when defined(nodejs):
  26. asm """
  27. process.on('exit', `quitProc`);
  28. """
  29. elif defined(js):
  30. asm """
  31. window.onbeforeunload = `quitProc`;
  32. """
  33. else:
  34. proc addAtExit(quitProc: proc() {.noconv.}) {.
  35. importc: "atexit", header: "<stdlib.h>".}
  36. proc callClosures() {.noconv.} =
  37. withLock gFunsLock:
  38. for i in countdown(gFuns.len-1, 0):
  39. let fun = gFuns[i]
  40. case fun.kind
  41. of kClosure: fun.fun1()
  42. of kNoconv: fun.fun2()
  43. gFuns.setLen(0)
  44. template fun() =
  45. if gFuns.len == 0:
  46. addAtExit(callClosures)
  47. proc addExitProc*(cl: proc () {.closure.}) =
  48. ## Adds/registers a quit procedure. Each call to `addExitProc` registers
  49. ## another quit procedure. They are executed on a last-in, first-out basis.
  50. # Support for `addExitProc` is done by Ansi C's facilities here.
  51. # In case of an unhandled exception the exit handlers should
  52. # not be called explicitly! The user may decide to do this manually though.
  53. withLock gFunsLock:
  54. fun()
  55. gFuns.add Fun(kind: kClosure, fun1: cl)
  56. proc addExitProc*(cl: proc() {.noconv.}) =
  57. ## overload for `noconv` procs.
  58. withLock gFunsLock:
  59. fun()
  60. gFuns.add Fun(kind: kNoconv, fun2: cl)
  61. when not defined(nimscript):
  62. proc getProgramResult*(): int =
  63. when defined(js) and defined(nodejs):
  64. asm """
  65. `result` = process.exitCode;
  66. """
  67. elif not defined(js):
  68. result = programResult
  69. else:
  70. doAssert false
  71. proc setProgramResult*(a: int) =
  72. # pending https://github.com/nim-lang/Nim/issues/14674
  73. when defined(js) and defined(nodejs):
  74. asm """
  75. process.exitCode = `a`;
  76. """
  77. elif not defined(js):
  78. programResult = a
  79. else:
  80. doAssert false