Program crash: GC destroys an object unexpectedly

jfondren julian.fondren at gmail.com
Wed Sep 15 23:07:45 UTC 2021


On Tuesday, 14 September 2021 at 20:59:14 UTC, Ali Çehreli wrote:
> On 9/14/21 9:56 AM, eugene wrote:
>
> > On Tuesday, 14 September 2021 at 16:43:50 UTC, jfondren wrote:
>
> >> The misaligned pointer and the
> >> reference-containing struct that vanishes on the return of
> your
> >> corresponding function are both problems for this.
> >
> > where did you find 'misaligned pointer'?...
>
> I think it's the align(1) for EpollEvent.
>
> I was able to reproduce the segmentation fault and was 
> seemingly able to fix it by making the EventSource class 
> references alive by adding a constructor:
>
> align (1) struct EpollEvent {
>     align(1):
>     uint event_mask;
>     EventSource es;
>
>   this(uint event_mask, EventSource es) {
>     this.event_mask = event_mask;
>     this.es = es;
>     living ~= es;  // <-- Introduced this constructor for this 
> line
>   }
>     /* just do not want to use that union, epoll_data_t */
> }
>
> // Here is the array that keeps EventSource alive:
> EventSource[] living;
>
> If that really is the fix, of course the references must be 
> taken out of that container when possible.
>
> Ali

Yep. This patch is sufficient to prevent the segfault:

```
diff --git a/engine/ecap.d b/engine/ecap.d
index 71cb646..d57829c 100644
--- a/engine/ecap.d
+++ b/engine/ecap.d
@@ -32,6 +32,7 @@ final class EventQueue {
      private int id;
      private bool done;
      private MessageQueue mq;
+    private EventSource[] sources;

      private this() {
          id = epoll_create1(0);
@@ -52,6 +53,7 @@ final class EventQueue {

      void registerEventSource(EventSource es) {
          auto e = EpollEvent(0, es);
+        sources ~= es;
          int r = epoll_ctl(id, EPOLL_CTL_ADD, es.id, &e);
          assert(r == 0, "epoll_ctl(ADD) failed");
      }
@@ -63,7 +65,10 @@ final class EventQueue {
      }

      void deregisterEventSource(EventSource es) {
+        import std.algorithm : countUntil, remove;
+
          auto e = EpollEvent(0, es);
+        sources = sources.remove(sources.countUntil(es));
          int r = epoll_ctl(id, EPOLL_CTL_DEL, es.id, &e);
          assert(r == 0, "epoll_ctl(DEL) failed");
      }
```

Going through the project and adding @safe: to the top of 
everything results in these errors: 
https://gist.github.com/jrfondren/c7f7b47be057273830d6a31372895895
some I/O, some @system functions, some weird C APIs ... and 
misaligned assignments to EpollEvent.es. So debugging with @safe 
isn't bad, but I'd still like rustc-style error codes:

```
engine/ecap.d(89): Error E415: field `EpollEvent.es` cannot 
assign to misaligned pointers in `@safe` code

$ dmd --explain E415

Yeah see, the garbage collector only looks for pointers at 
pointer-aligned addresses.
```


More information about the Digitalmars-d-learn mailing list