Bug #58402 ut/ut0ut.c compilation errors
Submitted: 22 Nov 2010 19:55 Modified: 17 Jul 2011 11:41
Reporter: Paul Dubois Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Compiling Severity:S3 (Non-critical)
Version:5.1.53, 5.1.59 OS:Linux
Assigned to: CPU Architecture:Any
Triage: Needs Triage: D3 (Medium)

[22 Nov 2010 19:55] Paul Dubois
Description:
On Linux, I get the following compilation errors if I configure with --with-debug or --with-debug=full. I see this with the just-released 5.1.53 source distribution, and with the current 5.1 Bazaar tree (5.1.54).

gcc -DHAVE_CONFIG_H -I. -I../../include -I../../include -I../../include -I../../regex -I../../storage/innobase/include -I../../sql -I.   -Wall -Wextra -Wunused -Wwrite-strings -Wno-strict-aliasing -Werror -Wdeclaration-after-statement -g -DSAFE_MUTEX -DSAFEMALLOC -O1   -DUNIV_LINUX -DUNIV_LINUX -MT libinnobase_a-ut0ut.o -MD -MP -MF .deps/libinnobase_a-ut0ut.Tpo -c -o libinnobase_a-ut0ut.o `test -f 'ut/ut0ut.c' || echo './'`ut/ut0ut.c
cc1: warnings being treated as errors
ut/ut0ut.c: In function ‘ut_print_namel’:
ut/ut0ut.c:498: error: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result
ut/ut0ut.c: In function ‘ut_copy_file’:
ut/ut0ut.c:519: error: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result
make[2]: *** [libinnobase_a-ut0ut.o] Error 1
make[2]: Leaving directory `/src/extern/MySQL/bzr-mysql/mysql-5.1-security/storage/innobase'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/src/extern/MySQL/bzr-mysql/mysql-5.1-security/storage'
make: *** [all-recursive] Error 1

If I do not configure with --with-debug[=full], compilation results in warnings, but the compile succeeds:

gcc -DHAVE_CONFIG_H -I. -I../../include -I../../include -I../../include -I../../regex -I../../storage/innobase/include -I../../sql -I.    -O1   -DUNIV_LINUX -DUNIV_LINUX -MT libinnobase_a-ut0ut.o -MD -MP -MF .deps/libinnobase_a-ut0ut.Tpo -c -o libinnobase_a-ut0ut.o `test -f 'ut/ut0ut.c' || echo './'`ut/ut0ut.c
ut/ut0ut.c: In function ‘ut_print_namel’:
ut/ut0ut.c:498: warning: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result
ut/ut0ut.c: In function ‘ut_copy_file’:
ut/ut0ut.c:519: warning: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result

I don't see the problem for, e.g., Mac OS X, for which my compile line looks like this, even though I configured with --with-debug=full:

gcc -DHAVE_CONFIG_H -I. -I../../include -I../../include -I../../include -I../../regex -I../../storage/innobase/include -I../../sql -I.   -Wall -Wextra -Wunused -Wwrite-strings -Wno-strict-aliasing -Werror -Wdeclaration-after-statement -g -DSAFE_MUTEX -DSAFEMALLOC -g -O2   -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT  -DDONT_DECLARE_CXA_PURE_VIRTUAL -MT libinnobase_a-ut0ut.o -MD -MP -MF .deps/libinnobase_a-ut0ut.Tpo -c -o libinnobase_a-ut0ut.o `test -f 'ut/ut0ut.c' || echo './'`ut/ut0ut.c

Possibly it is a gcc-version issue? I have gcc 4.4.5 on my Linux host, gcc 4.2.1 on my Mac OS X host.

How to repeat:
see above

Suggested fix:
workaround is to not configure with --with-debug.
[23 Nov 2010 0:18] Sveta Smirnova
Thank you for the report.

I can not compile with `./configure --with-debug` due to bug #57989 and can not repeat with ./BUILD/compile-* scripts. Which configure options do you use?
[23 Nov 2010 1:06] Paul Dubois
Here is my configuration script:

VERSION=50154

PREFIX="/var/mysql/$VERSION"
PORT=$VERSION

HANDLERS="
  --with-plugins=archive,blackhole,csv,example,federated,innobase,partition
"
DOCS="--without-docs --without-man"
OTHER="
  --with-debug=full
  --enable-community-features
  --enable-profiling
  --enable-local-infile
  --enable-thread-safe-client
  --with-comment=
  --with-debug
  --with-embedded-server
  --with-extra-charsets=all
  --without-readline
  --with-ssl
"
rm -f config.cache
CFLAGS=-O1 \
./configure \
  --prefix=$PREFIX \
  --localstatedir=$PREFIX/data \
  --with-unix-socket-path=$PREFIX/mysql.sock \
  --with-tcp-port=$PORT \
  $HANDLERS $DOCS $OTHER
[23 Nov 2010 1:11] Davi Arnaut
The warning is generated by a GCC tag in the system's headers.
[23 Nov 2010 20:15] Sveta Smirnova
I get different error:

g++ -DMYSQL_SERVER -DDEFAULT_MYSQL_HOME="\"/users/ssmirnova/blade12/build/mysql-5.1.53\"" -DMYSQL_DATADIR="\"/users/ssmirnova/blade12/build/mysql-5.1.53/var\"" -DSHAREDIR="\"/users/ssmirnova/blade12/build/mysql-5.1.53/share/mysql\"" -DPLUGINDIR="\"/users/ssmirnova/blade12/build/mysql-5.1.53/lib/mysql/plugin\"" -DHAVE_EVENT_SCHEDULER -DHAVE_CONFIG_H -I. -I../include -I../include -I../include -I../regex -I.    -Wall -Wextra -Wunused -Wwrite-strings -Wno-strict-aliasing -Werror -Wno-unused-parameter -g  -DSAFE_MUTEX -g -O2   -fno-implicit-templates -fno-exceptions -fno-rtti -MT debug_sync.o -MD -MP -MF .deps/debug_sync.Tpo -c -o debug_sync.o debug_sync.cc
cc1plus: warnings being treated as errors
debug_sync.cc: In function ‘void debug_sync_execute(THD*, st_debug_sync_action*)’:
debug_sync.cc:1721: error: ‘old_proc_info’ may be used uninitialized in this function
make[3]: *** [debug_sync.o] Error 1
make[3]: Leaving directory `/users/ssmirnova/blade12/mysql-5.1.53/sql'
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory `/users/ssmirnova/blade12/mysql-5.1.53/sql'
make[1]: *** [all] Error 2
make[1]: Leaving directory `/users/ssmirnova/blade12/mysql-5.1.53/sql'
make: *** [all-recursive] Error 1
[23 Nov 2010 20:29] Sveta Smirnova
Hm... my last error is bug #57997 although on Linux
[23 Nov 2010 21:23] Sveta Smirnova
I can not repeat the problem with gcc 4.4.5
[25 Nov 2010 23:18] Davi Arnaut
Hi Paul,

> Possibly it is a gcc-version issue? I have gcc 4.4.5 on my Linux host,
> gcc 4.2.1 on my Mac OS X host.

It is a issue related to the system headers, no GCC in particular. Looking at the error:

"error: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result"

it says that fwrite, which is declared in a system header (stdio.h), was declared with the attribute warn_unused_result which instructs GCC to issue a warning if the return value from fwrite is ignored in the code. This is something new in Linux distributions and the GNU C library they ship, where the maintainers started adding warn_unused_result to functions like fwrite.

First, I suggest you upgrade to the latest available version of the packages for your install. There has been a push against the indiscriminate use of this attribute and it has been reverted in some distributions. If the problem still persists, please specify your distro version so we can workaround it by checking the return value of fwrite.
[26 Nov 2010 16:38] Paul Dubois
Here are some version numbers. If these are not the packages you need, please let me know:

sys-kernel/linux-headers-2.6.36.1
sys-libs/glibc-2.12.1-r3
sys-kernel/gentoo-sources-2.6.36-r1 (latest available is r3, I have not upgraded, I can do so if that would be useful to try)
[27 Nov 2010 16:33] Paul Dubois
For the record:

Updating to sys-kernel/gentoo-sources-2.6.36-r3 made no difference. Same errors occur.
[8 Jun 2011 7:20] Stewart Smith
This warning means that InnoDB code is not checking return result of calls that it should be. i.e. the compiler is telling you there are bugs in InnoDB code that need to be fixed.
[17 Jul 2011 11:41] Valeriy Kravchuk
In current mysql-5.1 there is still no check for return value of fwrite in this place:

void
ut_copy_file(
/*=========*/
        FILE*   dest,   /* in: output file */
        FILE*   src)    /* in: input file to be appended to output */
{
        long    len = ftell(src);
        char    buf[4096];

        rewind(src);
        do {
                size_t  maxs = len < (long) sizeof buf
                        ? (size_t) len
                        : sizeof buf;
                size_t  size = fread(buf, 1, maxs, src);
                fwrite(buf, 1, size, dest);
                len -= (long) size;
                if (size < maxs) {
                        break;
                }
        } while (len > 0);
}

I think this is something to fix.
[30 Nov 2013 14:31] Hartmut Holzgraefe
fwrite return value is still ignored in 5.6.14, so in case of e.g. an interrupted system call there will be gaps in the copied file ...

5.7.2 now checks for an error, but in the wrong way, or actually
a number of wrong ways:

  if (fwrite(buf, 1, size, dest) != size) {
    perror("fwrite");
  } 

1) fwrite can succeed partially, so returning a value smaller 
   than the given size is not an error by itself, it can as
   well be due to a transient problem like an interrupted system
   call. So another fwrite for the remaining unwritten data should
   be attempted depending on the actual error code

2) just writing an "fwrite: ..." message to stderr using perror()
   without any information about the place where the error occurred
   (here: ut_copy_file(), which is a 'funny' name btw. as the function
   actually does a "cat", not a "copy"), or what output file it occured
   on ...

3) the function still continues after hitting the fwrite() error,
   so there will still be a gap in the appended data

Also fread() can also return a size smaller than requested if hitting
E_AGAIN or E_INTR, in this case ut_copy_file() would terminate instead
of retrying to read the remaining part of the requested range, and would
also ignore *all* following data ...

As ut_copy_file() only seems to be used when writing
to the error log / for SHOW STATUS information (for 
"LATEST DETECTED DEADLOCK" and "LATEST FOREIGN KEY ERROR" 
information sections) this isn't too critical as truncated
reads/writes wouldn't affect actual data files, but the code
still has a smell ...
[30 Nov 2013 15:07] Hartmut Holzgraefe
code with proper error handling should probably look more like this (untested)?

/**********************************************************************//**
Catenate files. */

void
ut_cat_file(
/*=========*/
        FILE*   dest,   /*!< in: output file */
        FILE*   src)    /*!< in: input file to be appended to output */
{
        char    buf[4096];

        rewind(src);
        do {
		size_t written = 0;
		size_t r_size = fread(buf, 1, sizeof(buf), src);

		if ((r_size == 0) && (errno != EINTR) && (errno != EAGAIN)) {
		        break;
		}
			
                while (r_size) {
                        size_t w_size = fwrite(buf + written, 1, r_size, dest);
		        if ((r_size == 0) && (errno != EINTR) && (errno != EAGAIN)) {
		                break;
		        }
		        r_size -= w_size;
		        written += w_size;
		}                
        } while (!feof(src));
}