Bug #9913 deinit not called when calling udf from trigger
Submitted: 14 Apr 2005 16:59 Modified: 19 May 2005 2:01
Reporter: Trevor Kramer Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: User-defined functions ( UDF ) Severity:S1 (Critical)
Version:5.0.3 OS:Linux (RedHat 4)
Assigned to: Dmitry Lenev CPU Architecture:Any

[14 Apr 2005 16:59] Trevor Kramer
Description:
When calling a udf from a trigger the udf is invoked with a call to init followed by a call to the function and the deinit method is never called leading to a huge memory leak if memory was allocated in the init call.

How to repeat:
compile this as a udf

#include <my_global.h>
#include <mysql.h>
#include <m_string.h>
                                                                                                                                                                            
#include <iostream>
                                                                                                                                                                            
namespace std {
  extern ostream cerr;
}
                                                                                                                                                                            
extern "C" {
    my_bool example_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
    void example_deinit(UDF_INIT *initid);
    char* example(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error);
}
                                                                                                                                                                            
my_bool example_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
    std::cerr << "example_init" << std::endl;
    return 0;
}
                                                                                                                                                                            
void example_deinit(UDF_INIT *initid) {
    std::cout << "example_deinit" << std::endl;
}
                                                                                                                                                                            
char* example(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error) {
    *is_null = 1;
    return NULL;
}

and install it with this command

CREATE FUNCTION example RETURNS STRING SONAME "library_name.so";

install a trigger on a table that uses the udf

create trigger example_trigger BEFORE INSERT ON test_table for each row BEGIN set NEW.test_column = example(NEW.test_column); END//

and look in the server log for output - you will see

example_init
example_init

with no calls to deinit

Suggested fix:
Don't call udfs from triggers
[15 Apr 2005 4:57] Jorge del Conde
Thanks for your bug-report.  I verified this with 5.0.4 from bk.
[30 Apr 2005 16:22] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/internals/24501
[9 May 2005 14:20] Dmitry Lenev
After investigating this problem I would say that we have similar problem in 4.1 with prepared statements. I.e. udf_init() function is called for each execution of prepared statement and udf_deinit() function is called only once when this statement is destroyed. Which is obviously wrong...
[9 May 2005 14:22] Dmitry Lenev
Fixed in 4.1.12 and 5.0.6
[19 May 2005 2:01] Paul DuBois
Noted in 4.1.12, 5.0.6 changelogs.