---
title: Crystal 1.12.0 is released!
version: 1.12.0
date: 2024-04-09
author: straight-shoota
---

We are announcing a new Crystal release with several new features and bug fixes.

Pre-built packages are available on [GitHub Releases](https://github.com/crystal-lang/crystal/releases/tag/1.12.0) and our official distribution channels.
See [crystal-lang.org/install](https://crystal-lang.org/install/) for instructions.

## Stats

This release includes [142 changes since 1.11.2](https://github.com/crystal-lang/crystal/pulls?q=is%3Apr+milestone%3A1.12.0)
by 14 contributors. We thank all the contributors for all the effort put into
improving the language! ❤️

## Changes

Below we list the most remarkable changes in the language, compiler and stdlib.
For more details, visit the [full changelog](https://github.com/crystal-lang/crystal/releases/tag/1.12.0).

### Breaking

Respect alignments above `alignof(Void*)` inside union values. **This is an ABI breaking change**. Crystal makes no guarantees about ABI stability. Most users won't be affected by this. ([#14279](https://github.com/crystal-lang/crystal/issues/14279))

_Thanks [@HertzDevil]_

### Process termination handler

[`Process.on_terminate`](https://crystal-lang.org/api/1.12.0/Process.html#on_terminate%28%26handler%3AProcess%3A%3AExitReason-%3E%29%3ANil-class-method) replaces [`Process.on_interrupt`](https://crystal-lang.org/api/1.12.0/Process.html#on_interrupt(%26handler%3A-%3E)%3ANil-class-method) as a more potent and portable API for responding to termination requests ([#13694](https://github.com/crystal-lang/crystal/pull/13694)).
All current uses of `on_interrupt` can be replaced by `on_terminate` with the effect of responding to more termination triggers.

| Method         | Unix                             | Windows                                                                                                                                                 |
| -------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `on_terminate` | `SIGINT`, `SIGHUP` and `SIGTERM` | <kbd>Ctrl</kbd> + <kbd>C</kbd>, <kbd>Ctrl</kbd> + <kbd>Break</kbd>, terminal close, windows logoff  and shutdown signals sent to a console application. |
| `on_interrupt` | `SIGINT`                         | <kbd>Ctrl</kbd> + <kbd>C</kbd> and <kbd>Ctrl</kbd> + <kbd>Break</kbd> signals sent to a console application                                             |

This removes the need for adding platform-specific handlers in your code base to handle terminations that were previously not covered by `on_interrupt`.

In addition, `on_terminate` also passes an instance of [`Process::ExitReason`](https://crystal-lang.org/api/1.12.0/Process/ExitReason.html) to the handler block, allowing it to react differently to specific termination events.

```crystal
Process.on_terminate do |reason|
  case reason
  when .interrupted?
    puts "terminating gracefully"
  when .terminal_disconnected?
    puts "reloading configuration"
  else
    puts "terminating forcefully"
    Process.exit(1)
  end
end

puts "Waiting for termination"
sleep
```

_Thanks [@stakach]_

### Concurrency

There are a couple minor improvements for concurrency which are foreshadowing more significant changes for the upcoming multi-threaded runtime enhancement.

- Backtraces for unhandled exceptions in [`spawn`](https://crystal-lang.org/api/1.12.0/toplevel.html#spawn%28%2A%2Cname%3AString%7CNil%3Dnil%2Csame_thread%3Dfalse%2C%26block%29-class-method) are printed at once in multi-threading mode to avoid unreadable interleaving lines ([#14220](https://github.com/crystal-lang/crystal/pull/14220)).
- When opening a [`File`](https://crystal-lang.org/api/1.12.0/File.html), it's now possible to disable blocking mode which is useful for pipes and character devices ([#14255](https://github.com/crystal-lang/crystal/pull/14255)).
- Some issues with atomics and locks got fixed and [`Atomic`](https://crystal-lang.org/api/1.12.0/Atomic.html) operations now receive an optional parameter to define the strength of ordering guarantees as [`Atomic::Ordering`](https://crystal-lang.org/api/1.12.0/Atomic/Ordering.html). New macro [`Atomic.fence`](https://crystal-lang.org/api/1.12.0/Atomic.html#fence%28ordering%3D%3Asequentially_consistent%29-macro) adds explicit memory barriers ([#14293](https://github.com/crystal-lang/crystal/pull/14293)).
- `Thread` got a `name` property to identify the thread. It can be set at initialization or for the current thread with `Thread.name=` ([#14257](https://github.com/crystal-lang/crystal/pull/14257)).
- Init schedulers before we spawn fibers ([#14339](https://github.com/crystal-lang/crystal/issues/14339)).
- Use per-scheduler stack pools, helping recycling stacks ([#14100](https://github.com/crystal-lang/crystal/issues/14100)).

_Thanks [@ysbaddaden]_

- Add memory barrier to `Mutex#unlock` on aarch64 ([#14272](https://github.com/crystal-lang/crystal/issues/14272)).

_Thanks [@jgaskins]_

### Libraries

We enabled support for OpenSSL 3.2 by fixing a bug in error handling for the OpenSSL 3.x series ([#14219](https://github.com/crystal-lang/crystal/issues/14219)).

_Thanks [@ysbaddaden]_

Our own LLVM extension library `libllvm_ext` is no longer required when linking LLVM >= 18 ([#14357](https://github.com/crystal-lang/crystal/pull/14357)) because all APIs are now directly exposed in `libllvm` directly. The Makefile automatically skips building `libllvm_ext.o` on LLVM 18 and above.

_Thanks [@HertzDevil]_

### Numeric

- Add [`BigRational#%`](https://crystal-lang.org/api/1.12.0/BigRational.html#%25%28other%3ABigRational%29%3ABigRational-instance-method), [`#tdiv`](https://crystal-lang.org/api/1.12.0/BigRational.html#tdiv(other:BigRational):BigRational-instance-method), [`#remainder`](https://crystal-lang.org/api/1.12.0/BigRational.html#remainder(other:BigRational):BigRational-instance-method) ([#14306](https://github.com/crystal-lang/crystal/issues/14306)).

_Thanks [@HertzDevil]_

### Operators with `=` suffix

Operators ending with `=` can now receive multiple parameters and blocks ([#14159](https://github.com/crystal-lang/crystal/pull/14159)) and they are properly forwarded by the [`delegate`](https://crystal-lang.org/api/1.12.0/Object.html#delegate(*methods,toobject)-macro) macro ([#14282](https://github.com/crystal-lang/crystal/pull/14282)).
The operator `#[]=` can be called with with a block using method syntax: `x.[]=() { }` ([#14161](https://github.com/crystal-lang/crystal/pull/14161))

_Thanks [@HertzDevil]_

### Windows progress

- Handle invalid parameter error in MSVC calls to prevent an immediate process exit ([#14313](https://github.com/crystal-lang/crystal/pull/14313))
- Install system dependencies in the Windows GUI installer ([#14328](https://github.com/crystal-lang/crystal/issues/14328))
- Automatically detect MSVC tools on Windows interpreter ([#14391](https://github.com/crystal-lang/crystal/pull/14391))
- Support `@[Link]`'s DLL search order in the interpreter on Windows ([#14146](https://github.com/crystal-lang/crystal/pull/14146))
- Reserve stack space on non-main threads for crash recovery on Windows ([#14187](https://github.com/crystal-lang/crystal/issues/14187)).
- [`FileUtils.mv`](https://crystal-lang.org/api/1.12.0/FileUtils.html#mv(src_path:Path%7cString,dest_path:Path%7cString):Nil-instance-method) works across filesystems on Windows ([#14320](https://github.com/crystal-lang/crystal/issues/14320)).

_Thanks [@HertzDevil]_

### Misc

- The time zone identifier `Etc/UTC` was added as an implicit alias to `UTC` and works without requiring a copy of the time zone database ([#14185](https://github.com/crystal-lang/crystal/pull/14185))

  _Thanks [@femto]_

- `Crystal::System::FileDescriptor::Handle` is a generic alias to the platform-specific type representing a file descriptor ([#14390](https://github.com/crystal-lang/crystal/pull/14390))

  _Thanks [@straight-shoota]_

- [`Hash#update`](https://crystal-lang.org/api/1.12.0/Hash.html#update(key:K,&:V-%3EV):V-instance-method) ([#14417](https://github.com/crystal-lang/crystal/issues/14417)) and [`Hash#put_if_absent`](https://crystal-lang.org/api/1.12.0/Hash.html#put_if_absent(key:K,&:K-%3EV):V-instance-method) ([#14427](https://github.com/crystal-lang/crystal/issues/14427)) no longer put duplicate keys if the block inserts the key.

  _Thanks [@HertzDevil]_

- New method [`Signal#trap_handler?`](https://crystal-lang.org/api/1.12.0/Signal.html#trap_handler?-instance-method) returns any existing handler for the signal ([#14126](https://github.com/crystal-lang/crystal/pull/14126))

  _Thanks [@stakach]_

- Added macro methods to several AST node types, `lib` & co ([#14218](https://github.com/crystal-lang/crystal/issues/14218)), `Primitive` ([#14263](https://github.com/crystal-lang/crystal/issues/14263)), `TypeOf` ([#14262](https://github.com/crystal-lang/crystal/issues/14262)), `Alias` ([#14261](https://github.com/crystal-lang/crystal/issues/14261)), `Asm` and `AsmOperand` ([#14268](https://github.com/crystal-lang/crystal/issues/14268)).

  _Thanks [@HertzDevil]_

### Compiler

- Add `CRYSTAL_CONFIG_CC` compiler config variable. This bakes in a reference to a specific compiler which is useful for 3rd party package managers such as Homebrew so that the compiler picks up the appropriate library paths ([#14318](https://github.com/crystal-lang/crystal/pull/14318)).

  _Thanks [@straight-shoota]_

- Support for `NO_COLOR` ([#14260](https://github.com/crystal-lang/crystal/pull/14260)), `--static` on Windows ([#14292](https://github.com/crystal-lang/crystal/pull/14292)), `--single-module` and `--threads` for `eval` and `spec` ([#14341](https://github.com/crystal-lang/crystal/pull/14341))

  _Thanks [@HertzDevil]_

- Preliminary support for Solaris/illumos has landed in the compiler and stdlib.

  _Thanks [@HertzDevil]_

- New CLI option `--frame-pointers` to control preservation of frame pointers ([#13860](https://github.com/crystal-lang/crystal/pull/13860))

  _Thanks [@refi64]_

- `short_reference` for top-level macros was changed to `::foo` instead of `top-level foo` ([#14203](https://github.com/crystal-lang/crystal/pull/14203))

  _Thanks [@femto]_

### Compiler dependencies

The compiler's own dependencies are now managed with `shards` ([#14365](https://github.com/crystal-lang/crystal/pull/14365)). The source code in `lib/` stays vendored in the repository, so `shards` is not required in order to build the compiler. It's only used for updating the dependencies in a much easier way than than with the previous approach based on `git subtree`.

_Thanks [@straight-shoota]_

### `crystal tool flags`

This release brings a new compiler tool: `crystal tool flags` ([#14234](https://github.com/crystal-lang/crystal/pull/14234)).
It prints all values passed to calls to [macro `flag?`](https://crystal-lang.org/api/1.12.0/Crystal/Macros.html#flag?(name):BoolLiteral-instance-method) so you can extract all compile time flags that a program recognizes.

_Thanks [@straight-shoota]_

### Formatter enhancements

Improved the formatter for `ProcLiteral`s ([#14209](https://github.com/crystal-lang/crystal/issues/14209)), `asm` with comments ([#14278](https://github.com/crystal-lang/crystal/issues/14278)), white space in `a.[b]` syntax ([#14346](https://github.com/crystal-lang/crystal/issues/14346)), calls without parentheses followed by doc comment ([#14354](https://github.com/crystal-lang/crystal/issues/14354)), whitespace in `foo ()` ([#14439](https://github.com/crystal-lang/crystal/issues/14439)).

_Thanks [@HertzDevil], [@straight-shoota]_

### Shards 0.18.0

The bundled shards release was updated to [0.18.0](https://github.com/crystal-lang/shards/releases/tag/v0.18.0).

This new shards release brings a couple of enhancements for Windows support, particularly
support for more cache directories ([#612](https://github.com/crystal-lang/shards/pull/612)), detection of symlink creation capability ([#617](https://github.com/crystal-lang/shards/pull/617)) and a lot more improvements on internal tooling.
Starting with this release, shards' output by default is only colored if stdout is a TTY instead of always ([#620](https://github.com/crystal-lang/shards/pull/620)).

_Thanks [@HertzDevil], [@straight-shoota]_

### Experimental: `ReferenceStorage`

Originally introduced in 1.11.0, the `ReferenceStorage` type was removed again in 1.11.1 due to compatibility issues with older versions of the standard library ([#14207](https://github.com/crystal-lang/crystal/issues/14207)).

We now have an improved implementation that shows no compatibility issues.
[`ReferenceStorage`](https://crystal-lang.org/api/1.12.0/ReferenceStorage.html) represents a static buffer for a reference allocation.

These APIs are still experimental and might be subject to change. We expect more features in this direction in future releases. Join the discussion about custom reference allocation at [#13481](https://github.com/crystal-lang/crystal/issues/13481).

_Thanks [@HertzDevil]_

### Deprecations

- Setter methods for timeouts with `Number` parameter ([#14372](https://github.com/crystal-lang/crystal/pull/14372)).
- Compile time flag `openbsd6.2` got removed ([#14233](https://github.com/crystal-lang/crystal/issues/14233)).
- The spec runner's state moved into `Spec::CLI`. This is only relevant for code which monkey-patches into the spec library ([#14170](https://github.com/crystal-lang/crystal/issues/14170)).

---

> **THANKS:**
> We have been able to do all of this thanks to the continued support of [84codes](https://www.84codes.com/) and every other [sponsor](/sponsors).
> To maintain and increase the development pace, donations and sponsorships are
> essential. [OpenCollective](https://opencollective.com/crystal-lang) is
> available for that.
>
> Reach out to [crystal@manas.tech](mailto:crystal@manas.tech)
> if you’d like to become a direct sponsor or find other ways to support Crystal.
> We thank you in advance!

[@stakach]: https://github.com/stakach
[@ysbaddaden]: https://github.com/ysbaddaden
[@jgaskins]: https://github.com/jgaskins
[@HertzDevil]: https://github.com/HertzDevil
[@femto]: https://github.com/femto
[@straight-shoota]: https://github.com/straight-shoota
[@refi64]: https://github.com/refi64
