Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-9282

Debian: the Lintian complains about "shlib-calls-exit" in ha_innodb.so

Details

    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

      Attachments

        Issue Links

          Activity

            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.

            marko Marko Mäkelä added a comment - 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.

            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.

            svoj Sergey Vojtovich added a comment - 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.

            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.

            marko Marko Mäkelä added a comment - 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.

            ok to push.

            jplindst Jan Lindström (Inactive) added a comment - ok to push.

            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.

            marko Marko Mäkelä added a comment - 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.

            People

              marko Marko Mäkelä
              svoj Sergey Vojtovich
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.