Parse transformery (Was: Re: Calling internal functions - foo::bar() ?)

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

Parse transformery (Was: Re: Calling internal functions - foo::bar() ?)

Kostis Sagonas-3
Mats Cronqvist wrote:

 > > We agree that export_all is bad. What we disagree on is the relative
 > > importance of troubleshooting tools vs. compiler optimization. This is
 > > hardly surprising since one of us is troubleshooting running systems
 > > all day and the other is developing compiler optimizations. :-)
 >
 > i was just going to comment to Kostis that for the AXD301, the choice between
 > a 5% compiler optimization and 5% better turnaround time on bug fixes is a
 > no-brainer (in favor of better debugging).

What my mail tried to express (and apparently it failed) was that for
a Programming Language Implementation the choice of satisfying the
occasional convenience of *some* users (no matter how important they
are) vs. adding a construct that effectively prohibits optimization
and thus penalizing *all* its user community should also be a no-brainer.

The difference is not that of a compiler writter vs. developer, it is
a matter of quantifying over the user community.

Erlang, as any language, has to have a compilation mode where analysis
or optimizations are allowed.  Being able to call arbitrary functions
from anywhere (when the compilation was done without +export_all or
some other option of the form +I_want_to_call_all_functions_from_anywhere)
prohibits not only optimizations, but also reasoning about properties
of the code.

This is my point.

I do not object to the :: construct, I strongly object to it when not
explicitly telling the compiler that you reserve the right to use it.
The default should be compilation *without* the ability to call internal
functions.  The opposite is bad not only for my compiler writter wishes,
but also software-engineering wise.

Best,
Kostis



Reply | Threaded
Open this post in threaded view
|

Parse transformery (Was: Re: Calling internal functions - foo::bar() ?)

Mats Cronqvist (ÄL2/EAB)


Kostis Sagonas wrote:

> Mats Cronqvist wrote:
>
>  > > We agree that export_all is bad. What we disagree on is the relative
>  > > importance of troubleshooting tools vs. compiler optimization. This is
>  > > hardly surprising since one of us is troubleshooting running systems
>  > > all day and the other is developing compiler optimizations. :-)
>  >
>  > i was just going to comment to Kostis that for the AXD301, the choice between
>  > a 5% compiler optimization and 5% better turnaround time on bug fixes is a
>  > no-brainer (in favor of better debugging).
>
> What my mail tried to express (and apparently it failed) was that for
> a Programming Language Implementation the choice of satisfying the
> occasional convenience of *some* users (no matter how important they
> are) vs. adding a construct that effectively prohibits optimization
> and thus penalizing *all* its user community should also be a no-brainer.

   i don't feel you failed in expressing yourself in the previous post. i just
don't agree, or rather, i think you're over-simplifying. if you excuse me
paraphrasing;
   here you have a choice between satisfying *some* users (the ones that need to
integrate and debug, possibly live, systems w/o access to the source code), vs.
penalizing *some* users (the ones that need a potential moderate performance
increase).
   as for the AXD301, we of course want both :>. however, to us increased
reliability is more important than increased speed.

   mats


Reply | Threaded
Open this post in threaded view
|

Parse transformery (Was: Re: Calling internal functions - foo::bar() ?)

Claes Wikström
On Tue, Mar 08, 2005 at 12:58:21PM +0100, Mats Cronqvist wrote:

>   here you have a choice between satisfying *some* users (the ones that
>   need to integrate and debug, possibly live, systems w/o access to the
> source code), vs. penalizing *some* users (the ones that need a potential
> moderate performance increase).
>   as for the AXD301, we of course want both :>. however, to us increased
> reliability is more important than increased speed.
>



Speaking for myself. The ability to call private functions
in _live_ systems far outweigh performance considerations
in the systems I have been involved in lately.

Therefore I almost always use -compile(export_all)
in most of my modules. Later ... way later when a
module has stabilized, I might (if I get the time)
do a later overhaul and explicitly export the API
functions.

So I am apparently valuing debugability higher than sw engineering
aspects as well as performance aspects.


/klacke


--
Claes Wikstrom                        -- Caps lock is nowhere and
http://www.hyber.org                  -- everything is under control          


Reply | Threaded
Open this post in threaded view
|

Parse transformery (Was: Re: Calling internal functions - foo::bar() ?)

Luke Gorrie-3
In reply to this post by Kostis Sagonas-3
Kostis Sagonas <kostis> writes:

> What my mail tried to express (and apparently it failed) was that for
> a Programming Language Implementation the choice of satisfying the
> occasional convenience of *some* users (no matter how important they
> are) vs. adding a construct that effectively prohibits optimization
> and thus penalizing *all* its user community should also be a no-brainer.

If you want a lot of real people to benefit from compiler
optimizations then please finish HiPE so that we can actually use it.
Lack of backtraces, memory leaks in code reloading, unclear limit on
volume of native code that can be loaded -- these are limitations
imposed for your convenience that prohibit actual use by most of the
user community. There's no use targeting idealized users who don't
really exist and "punishing" us poor fools who do.

On the other hand, if there really are people who never need to call
unexported functions, don't get into trouble when using a different
compiler for production vs. development, select exactly the right code
to native compile, and never have bugs that need live troubleshooting,
then please tell us who they are - they should be doing my job.

The rumour I heard is they're all programming in ML and Haskell :-(

-Luke (sad that Richard C. has moved on to new and exciting things and
       all my years of nagging him for HiPE backtraces were wasted :-)

.. IMHO.



Reply | Threaded
Open this post in threaded view
|

Port driver memory free

Eranga Udesh-5
In reply to this post by Mats Cronqvist (ÄL2/EAB)
Hi All,

There are 2 parameters, **rbuf and rlen in Port Driver entry "control. In
PORT_CONTROL_FLAG_BINARY mode, I should pass a driver_binary in **rbuf.
Usually rlen is 64, which mean **rbuf has 64 bytes, if I need to use that
without creating a new ErlDrvBinary. My questions are,

1. If my final ErlDrvBinary size is < 64 bytes and I use **rbuf without
allocating a new ErlDrvBinary, should I still call driver_free_binary or
driver_free to free that **rbuf memory before "control" function returns?

2. If my final ErlDrvBinary size is > 64 bytes and I allocate a new
driver_binary and assign to **rbuf, what will happen to the previous 64
buffer which was in **rbuf? Will the port or erlang garbage collecter free
that? Or do I need to free it inside the "control" function by calling
driver_free_binary or driver_free?

3. I (2) above, what will be the case if I use driver_realloc or
driver_realloc_binary? Will the previous 64 byes get released?

4. I (2) above, I still need to call driver_free_binary to free the newly
created driver_binary inside "control" function, correct?

5. If I call "set_port_control_flags(dd->port, 0)" to set the port output to
non-binary, do I need to free or clear the non-used space of **rbuf?

6. In above cased which free function, driver_free_binary or driver_free and
which allocation function, driver_alloc, driver_alloc_binary,
driver_realloc, driver_realloc_binary should I use?

Thanks in advance!
- Eranga




Reply | Threaded
Open this post in threaded view
|

Port driver memory free

Raimo Niskanen-3
The short answer is: do not free!

To elaborate:
* In binary mode, you must return a binary:
    ErlDrvBinary *binp = driver_alloc_binary(len);
    /* Copy len bytes of data to to binp->orig_bytes */
    *rbuf = (char *)binp;
    return len;
  The caller (the emulator) will increment the refcount and take care
  of deallocation when the binary is no longer used.
* In list mode, if the supplied result buffer is too small, you
  should allocate a new result buffer using driver_alloc(size),
  and the caller (the emulator) will free it it has fetched the
  result from it. Otherwise just write the result in the supplied
  result buffer. The emulator compares the returned buffer address
  with the supplied buffer address to see if you return an allocated
  buffer. So, if you set *rbuf, it _must_ be to something allocated
  with driver_alloc(size), because it _will_ be freed with
  driver_free(*rbuf). You can of course return an allocated buffer
  for any size, also less than 64 bytes.



casper2000a (Casper) writes:

> Hi All,
>
> There are 2 parameters, **rbuf and rlen in Port Driver entry "control. In
> PORT_CONTROL_FLAG_BINARY mode, I should pass a driver_binary in **rbuf.
> Usually rlen is 64, which mean **rbuf has 64 bytes, if I need to use that
> without creating a new ErlDrvBinary. My questions are,
>
> 1. If my final ErlDrvBinary size is < 64 bytes and I use **rbuf without
> allocating a new ErlDrvBinary, should I still call driver_free_binary or
> driver_free to free that **rbuf memory before "control" function returns?
>
> 2. If my final ErlDrvBinary size is > 64 bytes and I allocate a new
> driver_binary and assign to **rbuf, what will happen to the previous 64
> buffer which was in **rbuf? Will the port or erlang garbage collecter free
> that? Or do I need to free it inside the "control" function by calling
> driver_free_binary or driver_free?
>
> 3. I (2) above, what will be the case if I use driver_realloc or
> driver_realloc_binary? Will the previous 64 byes get released?
>
> 4. I (2) above, I still need to call driver_free_binary to free the newly
> created driver_binary inside "control" function, correct?
>
> 5. If I call "set_port_control_flags(dd->port, 0)" to set the port output to
> non-binary, do I need to free or clear the non-used space of **rbuf?
>
> 6. In above cased which free function, driver_free_binary or driver_free and
> which allocation function, driver_alloc, driver_alloc_binary,
> driver_realloc, driver_realloc_binary should I use?
>
> Thanks in advance!
> - Eranga
>
>

--

/ Raimo Niskanen, Erlang/OTP, Ericsson AB


Reply | Threaded
Open this post in threaded view
|

Port driver memory free

Eranga Udesh-5
Hi Raimo,

Thanks for the detailed explaination. Still I have 2 questions.

1. In PORT_CONTROL_FLAG_BINARY mode, control function should return a binary. So I usually
allocate a binary by calling driver_alloc_binary function. As per your explaination the emulater uses
driver_free to deallocate it. Will this create a problem? (allocate using driver_alloc_binary and
deallocate using driver_free)

2. Erlang Maual says at page ERTS->driver_entry->control "Note that this binary must be freed".

- Eranga



Quoting Raimo Niskanen : > Quoting Raimo Niskanen :

> The short answer is: do not free!
>
> To elaborate:
> * In binary mode, you must return a binary:
> ErlDrvBinary *binp = driver_alloc_binary(len);
> /* Copy len bytes of data to to binp->orig_bytes */
> *rbuf = (char *)binp;
> return len;
> The caller (the emulator) will increment the refcount and take care
> of deallocation when the binary is no longer used.
> * In list mode, if the supplied result buffer is too small, you
> should allocate a new result buffer using driver_alloc(size),
> and the caller (the emulator) will free it it has fetched the
> result from it. Otherwise just write the result in the supplied
> result buffer. The emulator compares the returned buffer address
> with the supplied buffer address to see if you return an allocated
> buffer. So, if you set *rbuf, it _must_ be to something allocated
> with driver_alloc(size), because it _will_ be freed with
> driver_free(*rbuf). You can of course return an allocated buffer
> for any size, also less than 64 bytes.
>
>
>
> casper2000a (Casper) writes:
>
> > Hi All,
> >
> > There are 2 parameters, **rbuf and rlen in Port Driver entry \"control. In
> > PORT_CONTROL_FLAG_BINARY mode, I should pass a driver_binary in **rbuf.
> > Usually rlen is 64, which mean **rbuf has 64 bytes, if I need to use that
> > without creating a new ErlDrvBinary. My questions are,
> >
> > 1. If my final ErlDrvBinary size is < 64 bytes and I use **rbuf without
> > allocating a new ErlDrvBinary, should I still call driver_free_binary or
> > driver_free to free that **rbuf memory before \"control\" function returns?
> >
> > 2. If my final ErlDrvBinary size is > 64 bytes and I allocate a new
> > driver_binary and assign to **rbuf, what will happen to the previous 64
> > buffer which was in **rbuf? Will the port or erlang garbage collecter free
> > that? Or do I need to free it inside the \"control\" function by calling
> > driver_free_binary or driver_free?
> >
> > 3. I (2) above, what will be the case if I use driver_realloc or
> > driver_realloc_binary? Will the previous 64 byes get released?
> >
> > 4. I (2) above, I still need to call driver_free_binary to free the newly
> > created driver_binary inside \"control\" function, correct?
> >
> > 5. If I call \"set_port_control_flags(dd->port, 0)\" to set the port output
> to
> > non-binary, do I need to free or clear the non-used space of **rbuf?
> >
> > 6. In above cased which free function, driver_free_binary or driver_free
> and
> > which allocation function, driver_alloc, driver_alloc_binary,
> > driver_realloc, driver_realloc_binary should I use?
> >
> > Thanks in advance!
> > - Eranga
> >
> >
>
> --
>
> / Raimo Niskanen, Erlang/OTP, Ericsson AB
>

--------------This mail sent through OmniBIS.com--------------



Reply | Threaded
Open this post in threaded view
|

Port driver memory free

Raimo Niskanen-3
1. No, driver_free is used in list mode; directly after the result list
   has been created. In binary mode the binary is not freed, it is
   passed to the receiving process and will be properly freed once the
   garbage collector finds it is not used anymore.
2. I guess the manual is unclear or even wrong. Like for plain result
   buffer you cannot free until after you have returned, which is
   impossible, so therefore, conceptually, the emulator frees the
   result buffer - even when it is a binary. (I hope I do not have to
   eat this mail if that statement proves wrong) Generally, if you
   allocate a binary you will have to free it when you do not use
   it anymore, but in this special case of returning it as a result;
   if you want to hang on to it you will have to increment its
   refcount before you return. But _if_ you keep the binary after
   returning it - you can not change it because the emulator, compiler
   and all programmers assume that a term can not change value.
   As a special feature, from R10B, you can also return NULL instead of
   a binary, which will arrive as [] to the receiving erlang process
   which is handy when you do not want to return anything, and want
   to do it fast.



casper2000a writes:

> Hi Raimo,
>
> Thanks for the detailed explaination. Still I have 2 questions.
>
> 1. In PORT_CONTROL_FLAG_BINARY mode, control function should return a binary. So I usually
> allocate a binary by calling driver_alloc_binary function. As per your explaination the emulater uses
> driver_free to deallocate it. Will this create a problem? (allocate using driver_alloc_binary and
> deallocate using driver_free)
>
> 2. Erlang Maual says at page ERTS->driver_entry->control "Note that this binary must be freed".
>
> - Eranga
>
>
>
> Quoting Raimo Niskanen : > Quoting Raimo Niskanen :
>
> > The short answer is: do not free!
> >
> > To elaborate:
> > * In binary mode, you must return a binary:
> > ErlDrvBinary *binp = driver_alloc_binary(len);
> > /* Copy len bytes of data to to binp->orig_bytes */
> > *rbuf = (char *)binp;
> > return len;
> > The caller (the emulator) will increment the refcount and take care
> > of deallocation when the binary is no longer used.
> > * In list mode, if the supplied result buffer is too small, you
> > should allocate a new result buffer using driver_alloc(size),
> > and the caller (the emulator) will free it it has fetched the
> > result from it. Otherwise just write the result in the supplied
> > result buffer. The emulator compares the returned buffer address
> > with the supplied buffer address to see if you return an allocated
> > buffer. So, if you set *rbuf, it _must_ be to something allocated
> > with driver_alloc(size), because it _will_ be freed with
> > driver_free(*rbuf). You can of course return an allocated buffer
> > for any size, also less than 64 bytes.
> >
> >
> >
> > casper2000a (Casper) writes:
> >
> > > Hi All,
> > >
> > > There are 2 parameters, **rbuf and rlen in Port Driver entry \"control. In
> > > PORT_CONTROL_FLAG_BINARY mode, I should pass a driver_binary in **rbuf.
> > > Usually rlen is 64, which mean **rbuf has 64 bytes, if I need to use that
> > > without creating a new ErlDrvBinary. My questions are,
> > >
> > > 1. If my final ErlDrvBinary size is < 64 bytes and I use **rbuf without
> > > allocating a new ErlDrvBinary, should I still call driver_free_binary or
> > > driver_free to free that **rbuf memory before \"control\" function returns?
> > >
> > > 2. If my final ErlDrvBinary size is > 64 bytes and I allocate a new
> > > driver_binary and assign to **rbuf, what will happen to the previous 64
> > > buffer which was in **rbuf? Will the port or erlang garbage collecter free
> > > that? Or do I need to free it inside the \"control\" function by calling
> > > driver_free_binary or driver_free?
> > >
> > > 3. I (2) above, what will be the case if I use driver_realloc or
> > > driver_realloc_binary? Will the previous 64 byes get released?
> > >
> > > 4. I (2) above, I still need to call driver_free_binary to free the newly
> > > created driver_binary inside \"control\" function, correct?
> > >
> > > 5. If I call \"set_port_control_flags(dd->port, 0)\" to set the port output
> > to
> > > non-binary, do I need to free or clear the non-used space of **rbuf?
> > >
> > > 6. In above cased which free function, driver_free_binary or driver_free
> > and
> > > which allocation function, driver_alloc, driver_alloc_binary,
> > > driver_realloc, driver_realloc_binary should I use?
> > >
> > > Thanks in advance!
> > > - Eranga
> > >
> > >
> >
> > --
> >
> > / Raimo Niskanen, Erlang/OTP, Ericsson AB
> >
>
> --------------This mail sent through OmniBIS.com--------------
>

--

/ Raimo Niskanen, Erlang/OTP, Ericsson AB


Reply | Threaded
Open this post in threaded view
|

Port driver memory free

Eranga Udesh-5
In reply to this post by Raimo Niskanen-3
Hi,

Today I noticed a funny thing with Port drivers "control" call.

I set the mode to PORT_CONTROL_FLAG_BINARY and use **rbuf as it is (without
reinitializing), since the space I need to output the binary message is less
than 64 bytes.

When I decode the received binary message in the emulator side, up to 7
bytes were exactly as I encoded in the C Port side. After that 8 position
onward I get some other value.

Then I created a new binary using driver_alloc_binary, even though the
output (encoded, total) is less than 64 bytes and tried, and viola, the
correct message came to emulator side.

If that a bug or something I do wrong?

Thanks!
- Eranga



-----Original Message-----
From: owner-erlang-questions
[mailto:owner-erlang-questions] On Behalf Of Raimo Niskanen
Sent: Thursday, March 17, 2005 2:17 PM
To: erlang-questions
Subject: Re: Port driver memory free

The short answer is: do not free!

To elaborate:
* In binary mode, you must return a binary:
    ErlDrvBinary *binp = driver_alloc_binary(len);
    /* Copy len bytes of data to to binp->orig_bytes */
    *rbuf = (char *)binp;
    return len;
  The caller (the emulator) will increment the refcount and take care
  of deallocation when the binary is no longer used.
* In list mode, if the supplied result buffer is too small, you
  should allocate a new result buffer using driver_alloc(size),
  and the caller (the emulator) will free it it has fetched the
  result from it. Otherwise just write the result in the supplied
  result buffer. The emulator compares the returned buffer address
  with the supplied buffer address to see if you return an allocated
  buffer. So, if you set *rbuf, it _must_ be to something allocated
  with driver_alloc(size), because it _will_ be freed with
  driver_free(*rbuf). You can of course return an allocated buffer
  for any size, also less than 64 bytes.



casper2000a (Casper) writes:

> Hi All,
>
> There are 2 parameters, **rbuf and rlen in Port Driver entry "control. In
> PORT_CONTROL_FLAG_BINARY mode, I should pass a driver_binary in **rbuf.
> Usually rlen is 64, which mean **rbuf has 64 bytes, if I need to use that
> without creating a new ErlDrvBinary. My questions are,
>
> 1. If my final ErlDrvBinary size is < 64 bytes and I use **rbuf without
> allocating a new ErlDrvBinary, should I still call driver_free_binary or
> driver_free to free that **rbuf memory before "control" function returns?
>
> 2. If my final ErlDrvBinary size is > 64 bytes and I allocate a new
> driver_binary and assign to **rbuf, what will happen to the previous 64
> buffer which was in **rbuf? Will the port or erlang garbage collecter free
> that? Or do I need to free it inside the "control" function by calling
> driver_free_binary or driver_free?
>
> 3. I (2) above, what will be the case if I use driver_realloc or
> driver_realloc_binary? Will the previous 64 byes get released?
>
> 4. I (2) above, I still need to call driver_free_binary to free the newly
> created driver_binary inside "control" function, correct?
>
> 5. If I call "set_port_control_flags(dd->port, 0)" to set the port output
to
> non-binary, do I need to free or clear the non-used space of **rbuf?
>
> 6. In above cased which free function, driver_free_binary or driver_free
and
> which allocation function, driver_alloc, driver_alloc_binary,
> driver_realloc, driver_realloc_binary should I use?
>
> Thanks in advance!
> - Eranga
>
>

--

/ Raimo Niskanen, Erlang/OTP, Ericsson AB



Reply | Threaded
Open this post in threaded view
|

Port driver memory free

Raimo Niskanen-3
Yes, you do it wrong. The returned value _must_ be a binary,
(or NULL for R10B or later). The code that takes care of the value
assumes it is a binary, so you have introduced something in your
system that is assumed to be a binary, but is actually stack allocated
plain memory. The emulator will probably crash much later because
memory has been trashed.

You will get partially correct behaviour because the receiving code
looks for the contents of the binary, and finds something there.
Unfortunately the header is not correct and it has not been allocated
with driver_alloc_binary(), but will later be freed with
driver_free_binary(), and both the contents and header will be
overwritten with garbage as soon as the emulator C stack grows.

Do not do that - you will get hurt!



casper2000a (Casper) writes:

> Hi,
>
> Today I noticed a funny thing with Port drivers "control" call.
>
> I set the mode to PORT_CONTROL_FLAG_BINARY and use **rbuf as it is (without
> reinitializing), since the space I need to output the binary message is less
> than 64 bytes.
>
> When I decode the received binary message in the emulator side, up to 7
> bytes were exactly as I encoded in the C Port side. After that 8 position
> onward I get some other value.
>
> Then I created a new binary using driver_alloc_binary, even though the
> output (encoded, total) is less than 64 bytes and tried, and viola, the
> correct message came to emulator side.
>
> If that a bug or something I do wrong?
>
> Thanks!
> - Eranga
>
>
>
> -----Original Message-----
> From: owner-erlang-questions
> [mailto:owner-erlang-questions] On Behalf Of Raimo Niskanen
> Sent: Thursday, March 17, 2005 2:17 PM
> To: erlang-questions
> Subject: Re: Port driver memory free
>
> The short answer is: do not free!
>
> To elaborate:
> * In binary mode, you must return a binary:
>     ErlDrvBinary *binp = driver_alloc_binary(len);
>     /* Copy len bytes of data to to binp->orig_bytes */
>     *rbuf = (char *)binp;
>     return len;
>   The caller (the emulator) will increment the refcount and take care
>   of deallocation when the binary is no longer used.
> * In list mode, if the supplied result buffer is too small, you
>   should allocate a new result buffer using driver_alloc(size),
>   and the caller (the emulator) will free it it has fetched the
>   result from it. Otherwise just write the result in the supplied
>   result buffer. The emulator compares the returned buffer address
>   with the supplied buffer address to see if you return an allocated
>   buffer. So, if you set *rbuf, it _must_ be to something allocated
>   with driver_alloc(size), because it _will_ be freed with
>   driver_free(*rbuf). You can of course return an allocated buffer
>   for any size, also less than 64 bytes.
>
>
>
> casper2000a (Casper) writes:
>
> > Hi All,
> >
> > There are 2 parameters, **rbuf and rlen in Port Driver entry "control. In
> > PORT_CONTROL_FLAG_BINARY mode, I should pass a driver_binary in **rbuf.
> > Usually rlen is 64, which mean **rbuf has 64 bytes, if I need to use that
> > without creating a new ErlDrvBinary. My questions are,
> >
> > 1. If my final ErlDrvBinary size is < 64 bytes and I use **rbuf without
> > allocating a new ErlDrvBinary, should I still call driver_free_binary or
> > driver_free to free that **rbuf memory before "control" function returns?
> >
> > 2. If my final ErlDrvBinary size is > 64 bytes and I allocate a new
> > driver_binary and assign to **rbuf, what will happen to the previous 64
> > buffer which was in **rbuf? Will the port or erlang garbage collecter free
> > that? Or do I need to free it inside the "control" function by calling
> > driver_free_binary or driver_free?
> >
> > 3. I (2) above, what will be the case if I use driver_realloc or
> > driver_realloc_binary? Will the previous 64 byes get released?
> >
> > 4. I (2) above, I still need to call driver_free_binary to free the newly
> > created driver_binary inside "control" function, correct?
> >
> > 5. If I call "set_port_control_flags(dd->port, 0)" to set the port output
> to
> > non-binary, do I need to free or clear the non-used space of **rbuf?
> >
> > 6. In above cased which free function, driver_free_binary or driver_free
> and
> > which allocation function, driver_alloc, driver_alloc_binary,
> > driver_realloc, driver_realloc_binary should I use?
> >
> > Thanks in advance!
> > - Eranga
> >
> >
>
> --
>
> / Raimo Niskanen, Erlang/OTP, Ericsson AB
>

--

/ Raimo Niskanen, Erlang/OTP, Ericsson AB


Reply | Threaded
Open this post in threaded view
|

Port driver memory free

Eranga Udesh-5
Raimo,

Actually I allocate a binary. Here's what I do,

----------------------- C Port -----------------------------
int gen_reply(char **rbuf, int rlen, int *rindex, void *buffer, int buflen)
{
        ErlDrvBinary *drv_binary;
        char *p;

        *rindex = 0;
        ........
        ........
        for (p = NULL;;) {
                if (ei_encode_version(p, rindex)
                                || ei_encode_tuple_header(p, rindex, 2)
                                || ei_encode_atom(p, rindex, "ok")
                                || ei_encode_binary(p, rindex, buffer,
buflen)) {
                        DBG("ei_encode failed");
                        return((int) ERL_DRV_ERROR_ERRNO);
                }
                if (p)
                        break;
                //if (*rindex > rlen) {
                        *rbuf = driver_alloc_binary(*rindex);
                //}
                drv_binary = (ErlDrvBinary *) *rbuf;
                p = drv_binary->orig_bytes;
                *rindex = 0;
        }

        drv_binary->orig_size = *rindex;
        ........
----------------------------------------------------------

I had to comment out the "(*rindex > rlen)" part since when it was there,
what I received in the emulator side was garbage after 8th char position.

------------------------- Emulator -----------------------
case catch binary_to_term(erlang:port_control(Port, Command,
term_to_binary(Args))) of
        {'EXIT', Reason} ->
        .......
----------------------------------------------------------

On the emulator side binary_to_term BIF didn't give any error. But once
receive the term, the binary part contain incorrect data after 8th char pos.


Thanks!
- Eranga


-----Original Message-----
From: owner-erlang-questions
[mailto:owner-erlang-questions] On Behalf Of Raimo Niskanen
Sent: Friday, March 18, 2005 2:31 PM
To: erlang-questions
Subject: Re: Port driver memory free

Yes, you do it wrong. The returned value _must_ be a binary,
(or NULL for R10B or later). The code that takes care of the value
assumes it is a binary, so you have introduced something in your
system that is assumed to be a binary, but is actually stack allocated
plain memory. The emulator will probably crash much later because
memory has been trashed.

You will get partially correct behaviour because the receiving code
looks for the contents of the binary, and finds something there.
Unfortunately the header is not correct and it has not been allocated
with driver_alloc_binary(), but will later be freed with
driver_free_binary(), and both the contents and header will be
overwritten with garbage as soon as the emulator C stack grows.

Do not do that - you will get hurt!



casper2000a (Casper) writes:

> Hi,
>
> Today I noticed a funny thing with Port drivers "control" call.
>
> I set the mode to PORT_CONTROL_FLAG_BINARY and use **rbuf as it is
(without
> reinitializing), since the space I need to output the binary message is
less

> than 64 bytes.
>
> When I decode the received binary message in the emulator side, up to 7
> bytes were exactly as I encoded in the C Port side. After that 8 position
> onward I get some other value.
>
> Then I created a new binary using driver_alloc_binary, even though the
> output (encoded, total) is less than 64 bytes and tried, and viola, the
> correct message came to emulator side.
>
> If that a bug or something I do wrong?
>
> Thanks!
> - Eranga
>
>
>
> -----Original Message-----
> From: owner-erlang-questions
> [mailto:owner-erlang-questions] On Behalf Of Raimo Niskanen
> Sent: Thursday, March 17, 2005 2:17 PM
> To: erlang-questions
> Subject: Re: Port driver memory free
>
> The short answer is: do not free!
>
> To elaborate:
> * In binary mode, you must return a binary:
>     ErlDrvBinary *binp = driver_alloc_binary(len);
>     /* Copy len bytes of data to to binp->orig_bytes */
>     *rbuf = (char *)binp;
>     return len;
>   The caller (the emulator) will increment the refcount and take care
>   of deallocation when the binary is no longer used.
> * In list mode, if the supplied result buffer is too small, you
>   should allocate a new result buffer using driver_alloc(size),
>   and the caller (the emulator) will free it it has fetched the
>   result from it. Otherwise just write the result in the supplied
>   result buffer. The emulator compares the returned buffer address
>   with the supplied buffer address to see if you return an allocated
>   buffer. So, if you set *rbuf, it _must_ be to something allocated
>   with driver_alloc(size), because it _will_ be freed with
>   driver_free(*rbuf). You can of course return an allocated buffer
>   for any size, also less than 64 bytes.
>
>
>
> casper2000a (Casper) writes:
>
> > Hi All,
> >
> > There are 2 parameters, **rbuf and rlen in Port Driver entry "control.
In
> > PORT_CONTROL_FLAG_BINARY mode, I should pass a driver_binary in **rbuf.
> > Usually rlen is 64, which mean **rbuf has 64 bytes, if I need to use
that
> > without creating a new ErlDrvBinary. My questions are,
> >
> > 1. If my final ErlDrvBinary size is < 64 bytes and I use **rbuf without
> > allocating a new ErlDrvBinary, should I still call driver_free_binary or
> > driver_free to free that **rbuf memory before "control" function
returns?
> >
> > 2. If my final ErlDrvBinary size is > 64 bytes and I allocate a new
> > driver_binary and assign to **rbuf, what will happen to the previous 64
> > buffer which was in **rbuf? Will the port or erlang garbage collecter
free
> > that? Or do I need to free it inside the "control" function by calling
> > driver_free_binary or driver_free?
> >
> > 3. I (2) above, what will be the case if I use driver_realloc or
> > driver_realloc_binary? Will the previous 64 byes get released?
> >
> > 4. I (2) above, I still need to call driver_free_binary to free the
newly
> > created driver_binary inside "control" function, correct?
> >
> > 5. If I call "set_port_control_flags(dd->port, 0)" to set the port
output

> to
> > non-binary, do I need to free or clear the non-used space of **rbuf?
> >
> > 6. In above cased which free function, driver_free_binary or driver_free
> and
> > which allocation function, driver_alloc, driver_alloc_binary,
> > driver_realloc, driver_realloc_binary should I use?
> >
> > Thanks in advance!
> > - Eranga
> >
> >
>
> --
>
> / Raimo Niskanen, Erlang/OTP, Ericsson AB
>

--

/ Raimo Niskanen, Erlang/OTP, Ericsson AB