[racket] Some problem with hash-update!

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon Sep 15 01:58:08 EDT 2014

I think that changing `_pointer` to `_DWORD` can't be the real answer,
since `_pointer` is at least as large as `_DWORD`.

But I agree that you should use `malloc`, and you should also supply
'atomic-interior:

 (malloc _DWORD 'atomic-interior)

The 'atomic-interior flag ensures that the allocated memory does not
move during an invocation of the callback.

Along similar lines, I think you need to add

 #:malloc-mode 'atomic-interior

to the declaration of `_CMN_ERROR`.

You may need to copy the `filter` argument into non-moving memory, but
that's probably not an issue if it's always "".

At Mon, 15 Sep 2014 11:07:52 +0700 (NOVT), "Evgeny Odegov" wrote:
> More complete example:
> http://pasterack.org/pastes/25901
> 
> I guess I've found reason of the problem.
> 
> I think the problem was in that line:
> (define lpdwItems (make-bytes (ctype-sizeof _pointer) 0))
> 
> I've changed it to:
> (define lpdwItems (make-bytes (ctype-sizeof _DWORD) 0))
> 
> There is no visible problems now, but I doubt that applying `make-bytes'
> here is right.
> 
> Should I use `malloc' in such cases?
> 
> 
> Anyway, sorry for the noise.
> 
> 
> > My best guess is that it's an issue with memory management, because
> > memory management gets a lot trickier when you call a function that can
> > call back into Racket. A GC can happen during the callback, and
> > therefore during the dynamic extent of the foreign-function call, which
> > can move arguments that were passed to the foreign function, for example.
> >
> > Would it be possible to provide a complete example?
> >
> > At Sat, 13 Sep 2014 22:45:28 +0700 (NOVT), "Evgeny Odegov" wrote:
> >> Oh, I'm wrong. The last code is not equivalent to initial.
> >> The equivalent code has this problem:
> >>
> >> (define result (make-hash))
> >> (define big-list (list))
> >> (define (callback dwTextID lpszInfoText lpvUser)
> >>   (if (equal? lpszInfoText "")
> >>       (set! big-list (append big-list (list dwTextID)))
> >>       (hash-update! result
> >>                     lpszInfoText
> >>                     (lambda (id-lst)
> >>                       (define v (list dwTextID))
> >>                       (append id-lst v))
> >>                     '()))
> >>   #t)
> >>
> >>
> >> The code with `cons' instead `append' works fine:
> >>
> >> (define result (make-hash))
> >> (define (callback dwTextID lpszInfoText lpvUser)
> >>   (hash-update! result
> >>                 lpszInfoText
> >>                 (lambda (id-lst)
> >>                   (define new-id-lst (cons dwTextID id-lst))
> >>                   (unless (list? new-id-lst)
> >>
> >>                     (error "~v" new-id-lst))
> >>                   new-id-lst)
> >>                 '())
> >>   #t)
> >>
> >>
> >>
> >>
> >> ____________________
> >>   Racket Users list:
> >>   http://lists.racket-lang.org/users
> >

Posted on the users mailing list.