[MDEV-9282] Debian: the Lintian complains about "shlib-calls-exit" in ha_innodb.so Created: 2015-12-14  Updated: 2018-01-29  Resolved: 2016-12-28

Status: Closed
Project: MariaDB Server
Component/s: Storage Engine - InnoDB, Storage Engine - XtraDB
Affects Version/s: 10.0
Fix Version/s: 10.1.21

Type: Bug Priority: Major
Reporter: Sergey Vojtovich Assignee: Marko Mäkelä
Resolution: Fixed Votes: 0
Labels: innodb, xtradb

Issue Links:
PartOf
is part of MDEV-8378 Debian: the Lintian complains about m... Closed
is part of MDEV-10382 Using systemd, mariadb doesn't restar... Closed
Problem/Incident
causes MDEV-13284 mariadb-server: fil_load_single_table... Closed

 Description   

This is a split from MDEV-8378, priority and fix version inherited.

Lintian reports: http://labs.seravo.fi/~otto/mariadb-repo/mariadb-10.0-sid-amd64/lintian-0f7cb30.log and https://lintian.debian.org/tags/shlib-calls-exit.html

The listed shared library calls the C library exit() or _exit() functions.

In the case of an error, the library should instead return an appropriate error code to the calling program which can then determine how to handle the error, including performing any required clean-up.

In most cases, removing the call should be discussed with upstream, particularly as it may produce an ABI change.

Severity: wishlist, Certainty: possible

Check: shared-libs, Type: binary, udeb

This tag is marked experimental, which means that the code that generates it is not as well-tested as the rest of Lintian and might still give surprising results. Feel free to ignore experimental tags that do not seem to make sense, though of course bug reports are always welcome.

nm ./storage/innobase/ha_innodb.so|grep exit

                 U __cxa_atexit@@GLIBC_2.2.5
                 U exit@@GLIBC_2.2.5
00000000004738b0 b mutex_exit_count
                 U pthread_exit@@GLIBC_2.2.5
000000000013bdf0 t _Z13os_mutex_exitP10os_mutex_t
000000000001ec94 t _Z13os_mutex_exitP10os_mutex_t.part.2
000000000013c940 t _Z14os_thread_exitPv
00000000000b9e50 t _Z15hash_mutex_exitP12hash_table_tm
00000000000b9fe0 t _Z19hash_mutex_exit_allP12hash_table_t
0000000000159f90 t _Z19pars_exit_statementv
00000000000ba050 t _Z23hash_mutex_exit_all_butP12hash_table_tP10ib_mutex_t
0000000000078f20 t _Z25dict_mutex_exit_for_mysqlv
00000000001a82f0 t _Z26srv_conc_force_exit_innodbP5trx_t
0000000000134dd0 T _Z28os_file_handle_error_no_exitPKcS0_m
000000000007ccb0 t _Z38dict_table_wait_for_bg_threads_to_exitP12dict_table_tm
000000000009ccb0 t _Z9exit_stepP9que_thr_t
000000000001d135 t _ZL19pfs_mutex_exit_funcP10ib_mutex_t
0000000000077520 t _ZL19pfs_mutex_exit_funcP10ib_mutex_t
000000000009cd30 t _ZL19pfs_mutex_exit_funcP10ib_mutex_t
00000000000bace0 t _ZL19pfs_mutex_exit_funcP10ib_mutex_t
00000000000de530 t _ZL19pfs_mutex_exit_funcP10ib_mutex_t
000000000001db33 t _ZL19pfs_mutex_exit_funcP10ib_mutex_t
00000000001145f0 t _ZL19pfs_mutex_exit_funcP10ib_mutex_t
00000000001a9450 t _ZL19pfs_mutex_exit_funcP10ib_mutex_t
00000000001aee80 t _ZL19pfs_mutex_exit_funcP10ib_mutex_t
00000000001a96c0 t _ZL21srv_purge_should_exitm
0000000000134920 t _ZL30os_file_handle_error_cond_exitPKcS0_mm.constprop.29



 Comments   
Comment by Marko Mäkelä [ 2016-12-01 ]

In MariaDB 10.1, InnoDB calls exit() in quite a few places:

storage/innobase/api/api0misc.cc:189:                exit(1);
storage/innobase/buf/buf0dblwr.cc:232:		exit(EXIT_FAILURE);
storage/innobase/buf/buf0dblwr.cc:253:		exit(EXIT_FAILURE);
storage/innobase/buf/buf0dblwr.cc:269:			exit(EXIT_FAILURE);
storage/innobase/fil/fil0fil.cc:4604:		exit(1);
storage/innobase/fts/fts0blex.cc:1615:	exit( YY_EXIT_FAILURE );
storage/innobase/fts/fts0tlex.cc:1608:	exit( YY_EXIT_FAILURE );
storage/innobase/log/log0log.cc:832:			" Calling exit(1).\n",
storage/innobase/log/log0log.cc:835:		exit(1);
storage/innobase/log/log0log.cc:2554:			exit(1);
storage/innobase/log/log0recv.cc:2038:				exit(1);
storage/innobase/log/log0recv.cc:2051:					exit(1);
storage/innobase/log/log0recv.cc:2069:				exit(1);
storage/innobase/log/log0recv.cc:3637:			exit(1);
storage/innobase/log/log0recv.cc:3650:			exit(1);
storage/innobase/log/log0recv.cc:3672:		exit(1);
storage/innobase/os/os0file.cc:721:Conditionally exits (calling exit(3)) based on should_exit value and the
storage/innobase/os/os0file.cc:730:	ibool		should_exit,	/*!< in: call exit(3) if unknown error
storage/innobase/os/os0file.cc:817:			exit(1);
storage/innobase/os/os0thread.cc:162:		exit(1);
storage/innobase/os/os0thread.cc:177:		exit(1);
storage/innobase/row/row0mysql.cc:665:		exit(1);
storage/innobase/row/row0undo.cc:367:			exit(1);
storage/innobase/srv/srv0start.cc:603:		exit(3);						\
storage/innobase/srv/srv0start.cc:2923:		exit(1);

This is probably what it should do instead:

storage/innobase/pars/lexyy.cc:967:#define exit(A) 	ut_error
storage/innobase/pars/lexyy.cc:2916:	exit( YY_EXIT_FAILURE );
storage/innobase/pars/pars0lex.l:65:#define exit(A) 	ut_error

It is rather useless to call exit(), because it would not leave a core dump behind.
It would be better to call abort() so that the issue can be analyzed.

I did some exit() removal in the MySQL 5.7 startup code, but most notably, InnoDB I/O threads will easily call exit() when encountering bad files. This causes occasional debug assertions in other threads, and some workarounds have been added to make such crashes less likely.
The proper fix would be to propagate errors from I/O threads all the way to the client. It would be a huge refactoring task. InnoDB eagerly commits suicide (ut_error) in certain classes of errors (out of memory, corruption) instead of returning an error.

In MariaDB 10.2 (and MySQL 5.7) the only exit() call from InnoDB is in the function srv_fatal_error(), which is called from os_file_handle_error_cond_exit() and innobase_start_or_create_for_mysql(). The latter call could be removed rather easily, but the calls from I/O threads would require considerably more effort.

Comment by Sergey Vojtovich [ 2016-12-01 ]

marko, would you like to take over this bug? I think it doesn't make much sense to fix this in 10.1, since we're attempting to push 10.2 to debian now.

Comment by Marko Mäkelä [ 2016-12-01 ]

Taking this bug. I think that at startup, we can properly return the error to the caller instead of calling exit().
In I/O threads, we can invoke abort(). Those users who do not like core dumps can disable them.

Comment by Jan Lindström (Inactive) [ 2016-12-28 ]

ok to push.

Comment by Marko Mäkelä [ 2016-12-28 ]

I successfully tested my patch with the following in the build directory:

nm storage/innobase/ha_innodb.so |grep -w exit
nm storage/xtradb/libxtradb.a |grep -w exit
mysql-test/mtr --parallel=auto --force --suite=innodb,innodb_zip,innodb_fts

The first commands did not generate any output, and the tests passed.

Generated at Thu Feb 08 07:33:30 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.