Bug #35916 logging to stderr in a UDF does not work if MySQL is run as service
Submitted: 8 Apr 2008 22:58 Modified: 21 Oct 2009 6:51
Reporter: Roland Bouman Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: User-defined functions ( UDF ) Severity:S2 (Serious)
Version:5.1.23 OS:Windows (xp pro)
Assigned to: CPU Architecture:Any

[8 Apr 2008 22:58] Roland Bouman
Description:
When writing to stderr when inside a UDF the line should appear in the mysql error log (file pointed to by log_error server variable)

When starting mysqld from the commandline, this works. It does not work when MySQL is run as a windows service.

How to repeat:
compile attached source file using this line:

cl udf_lightspeed_sequence.c /link /dll /out:udf_lightspeed_sequence.dll

(or with MS VC++)

put it i the plugin dir and create the function:

CREATE FUNCTION lightspeed RETURNS INTEGER SONAME 'udf_lightspeed_sequence.dll';

SELECT lightspeed()

this logs 3 lines in the error log when mysql is ran from the command line. However, if mysql is stopped and ran as service, the logging does not take place

Suggested fix:
please log even when running as service
[8 Apr 2008 22:59] Roland Bouman
UDF

Attachment: udf_lightspeed_sequence.c (text/x-csrc), 462 bytes.

[8 Apr 2008 23:13] Vladislav Vaintroub
Verified as described. Additionally, to get debug info, one may compile
with /Zi /MTd.

Partial Workaround: don't use stdout/stderr in UDF directly, fopen the .err file with "a+".
[10 Apr 2008 20:50] Roland Bouman
I would like to add that I don't really see the workaround working.

A proposed workaround would be to have the UDF open a file (possibly the error log) itself. However this can never be a serious alternative in a production environment - first of all it would put a tremendous burden on system administrators in purging all those logs, second it would complicate the UDF implementors job of writing production level UDFs. 

I gathered from Vladislav that stderr/stdout is not really supposed to work at all when running a windows service - but in that case, I am wonder what that would mean for all other occurrences of fprintf(stderr,...) in the mysql source code.
[20 Jun 2008 7:45] 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/commits/48217

2672 Alexey Botchkov	2008-06-20
      Bug#35916 logging to stderr in a UDF does not work if MySQL runs as a service.
      
      When MySQL works as a service on Windows fprintf(stderr,..) doesn't work in dll.
      Besides writing to the errlog with the plain fprintf(stderr, ) doesn't work well - we
      need to provide sql_print_error function somehow.
      So this function is provided by calling setup_log_function() from the udf's library.
[18 Aug 2008 13:20] Alexey Botchkov
This problem is addressed by WL#2940
[4 Nov 2008 16:23] Sergei Golubchik
It's expected behavior.
windows services cannot write to stdout/stderr. So, if your UDF is loaded in the server which is run as a service, it'll be subject to the same limitation.
[14 Oct 2009 7:36] Sergei Golubchik
clarification: windows service don't get a console,
but if stdout/stderr are redirected to a file, they should work.

MySQL does redirect stderr to a file, but (according to Vlad) because file handles and streams are implemented in C runtime and mysqld.exe is linked with it statically, UDF gets its own copy of C runtime, and its own stderr.

This is something we could fix, I think.
[14 Oct 2009 9:34] Vladislav Vaintroub
The actual problem is that server and UDF are using different C runtime libraries . Server is linked with static C runtime, and this means UDF necessarily uses another C runtime. Posix file descriptors are specific to C runtime and not shared between the mysqld executable and UDF's DLL.

If server redirects its stderr to a file, UDF's C runtime would not know this.

Still, the logging to stderr should be possible with the some mix of Windows API and C runtime functionality like below.

void use_server_stderr()
{
  int server_out_fd = _open_osfhandle((intptr_t)GetStdHandle (STD_ERROR_HANDLE),0);
dup2(server_out_fd, fileno(stderr));
}

This code retrieves Windows STD_ERROR HANDLE (which is correctly set when server did freopen()), creates a C-runtime file descriptor from this HANDLE and makes stderr use this descriptor.
[21 Oct 2009 6:51] Roland Bouman
Hi all,

just want to say, I don't understand why this was triaged as a feature request. If I understand Vladislav's comments correctly, it seems to me that the is a bug in the way the error file was opened under windows.
[26 Jul 2010 8:17] Roel Van de Paar
Any updates on this?