2020-03-26 16:58:50 +00:00
# include <signal.h>
# include <setjmp.h>
2020-03-26 17:53:57 +00:00
# include <unistd.h>
2020-03-26 16:58:50 +00:00
2020-10-03 22:48:24 +00:00
# ifdef __linux__
# include <sys/mman.h>
# endif
2022-04-16 22:09:20 +00:00
# include <sys/types.h>
# include <pwd.h>
# include <grp.h>
2019-03-12 19:30:59 +00:00
# include <new>
2018-04-05 19:28:07 +00:00
# include <iostream>
2018-04-05 14:27:39 +00:00
# include <vector>
2018-04-05 19:28:07 +00:00
# include <string>
2020-10-04 08:24:36 +00:00
# include <tuple>
2018-11-26 00:56:50 +00:00
# include <utility> /// pair
2017-11-12 12:58:40 +00:00
2021-12-11 18:25:23 +00:00
# include "config_tools.h"
2018-06-19 18:09:09 +00:00
2018-01-15 19:07:47 +00:00
# include <Common/StringUtils/StringUtils.h>
2021-01-07 02:56:57 +00:00
# include <Common/getHashOfLoadedBinary.h>
2021-06-02 04:48:31 +00:00
# include <Common/IO.h>
2022-04-16 22:09:20 +00:00
# include <IO/ReadHelpers.h>
2016-10-25 12:14:27 +00:00
2021-10-02 07:13:14 +00:00
# include <base/phdr_cache.h>
# include <base/scope_guard.h>
2019-07-24 15:26:23 +00:00
2022-04-16 22:09:20 +00:00
namespace DB
{
namespace ErrorCodes
{
extern const int SYSTEM_ERROR ;
extern const int BAD_ARGUMENTS ;
}
}
2016-10-31 19:54:49 +00:00
/// Universal executable for various clickhouse applications
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_SERVER
2016-11-11 17:01:02 +00:00
int mainEntryClickHouseServer ( int argc , char * * argv ) ;
2018-02-15 20:57:08 +00:00
# endif
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_CLIENT
2017-03-24 15:05:54 +00:00
int mainEntryClickHouseClient ( int argc , char * * argv ) ;
2018-02-15 20:57:08 +00:00
# endif
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_LOCAL
2017-03-24 15:05:54 +00:00
int mainEntryClickHouseLocal ( int argc , char * * argv ) ;
2018-02-15 20:57:08 +00:00
# endif
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_BENCHMARK
2017-03-24 15:05:54 +00:00
int mainEntryClickHouseBenchmark ( int argc , char * * argv ) ;
2018-02-15 20:57:08 +00:00
# endif
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_EXTRACT_FROM_CONFIG
2017-03-24 15:05:54 +00:00
int mainEntryClickHouseExtractFromConfig ( int argc , char * * argv ) ;
2018-06-05 20:09:51 +00:00
# endif
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_COMPRESSOR
2017-09-20 14:12:12 +00:00
int mainEntryClickHouseCompressor ( int argc , char * * argv ) ;
2018-06-05 20:09:51 +00:00
# endif
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_FORMAT
2017-11-11 01:04:14 +00:00
int mainEntryClickHouseFormat ( int argc , char * * argv ) ;
2018-02-15 20:57:08 +00:00
# endif
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_COPIER
2017-10-13 19:13:41 +00:00
int mainEntryClickHouseClusterCopier ( int argc , char * * argv ) ;
2018-02-15 20:57:08 +00:00
# endif
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_OBFUSCATOR
2018-06-16 00:27:59 +00:00
int mainEntryClickHouseObfuscator ( int argc , char * * argv ) ;
# endif
2020-09-07 03:22:47 +00:00
# if ENABLE_CLICKHOUSE_GIT_IMPORT
int mainEntryClickHouseGitImport ( int argc , char * * argv ) ;
# endif
2021-05-12 10:39:07 +00:00
# if ENABLE_CLICKHOUSE_KEEPER
int mainEntryClickHouseKeeper ( int argc , char * * argv ) ;
# endif
2021-06-17 16:32:50 +00:00
# if ENABLE_CLICKHOUSE_KEEPER
int mainEntryClickHouseKeeperConverter ( int argc , char * * argv ) ;
# endif
2021-08-28 20:21:05 +00:00
# if ENABLE_CLICKHOUSE_STATIC_FILES_DISK_UPLOADER
int mainEntryClickHouseStaticFilesDiskUploader ( int argc , char * * argv ) ;
2021-06-18 11:21:05 +00:00
# endif
2020-08-08 18:38:34 +00:00
# if ENABLE_CLICKHOUSE_INSTALL
int mainEntryClickHouseInstall ( int argc , char * * argv ) ;
2020-08-08 20:42:10 +00:00
int mainEntryClickHouseStart ( int argc , char * * argv ) ;
int mainEntryClickHouseStop ( int argc , char * * argv ) ;
int mainEntryClickHouseStatus ( int argc , char * * argv ) ;
int mainEntryClickHouseRestart ( int argc , char * * argv ) ;
2020-08-08 18:38:34 +00:00
# endif
2018-08-07 17:57:44 +00:00
2021-01-07 02:56:57 +00:00
int mainEntryClickHouseHashBinary ( int , char * * )
{
/// Intentionally without newline. So you can run:
/// objcopy --add-section .note.ClickHouse.hash=<(./clickhouse hash-binary) clickhouse
std : : cout < < getHashOfLoadedBinaryHex ( ) ;
return 0 ;
}
2020-10-04 08:24:36 +00:00
# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
2016-10-25 12:14:27 +00:00
2017-09-20 13:41:13 +00:00
namespace
2016-10-25 12:14:27 +00:00
{
2016-10-31 19:54:49 +00:00
2017-09-20 13:41:13 +00:00
using MainFunc = int ( * ) ( int , char * * ) ;
2021-12-06 18:27:06 +00:00
# if !defined(FUZZING_MODE)
2017-09-20 13:41:13 +00:00
/// Add an item here to register new application
2021-12-06 18:27:06 +00:00
std : : pair < const char * , MainFunc > clickhouse_applications [ ] =
2017-09-20 13:41:13 +00:00
{
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_LOCAL
2017-09-20 13:41:13 +00:00
{ " local " , mainEntryClickHouseLocal } ,
2018-02-15 20:57:08 +00:00
# endif
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_CLIENT
2017-09-20 13:41:13 +00:00
{ " client " , mainEntryClickHouseClient } ,
2018-02-15 20:57:08 +00:00
# endif
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_BENCHMARK
2017-09-20 13:41:13 +00:00
{ " benchmark " , mainEntryClickHouseBenchmark } ,
2018-02-15 20:57:08 +00:00
# endif
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_SERVER
2017-09-20 13:41:13 +00:00
{ " server " , mainEntryClickHouseServer } ,
2018-02-15 20:57:08 +00:00
# endif
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_EXTRACT_FROM_CONFIG
2017-09-20 13:41:13 +00:00
{ " extract-from-config " , mainEntryClickHouseExtractFromConfig } ,
2018-06-06 16:05:53 +00:00
# endif
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_COMPRESSOR
2017-11-11 01:04:14 +00:00
{ " compressor " , mainEntryClickHouseCompressor } ,
2018-06-06 16:05:53 +00:00
# endif
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_FORMAT
2017-11-12 12:58:40 +00:00
{ " format " , mainEntryClickHouseFormat } ,
2018-02-15 20:57:08 +00:00
# endif
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_COPIER
2018-01-11 20:51:30 +00:00
{ " copier " , mainEntryClickHouseClusterCopier } ,
2018-02-15 20:57:08 +00:00
# endif
2020-05-27 21:58:46 +00:00
# if ENABLE_CLICKHOUSE_OBFUSCATOR
2018-06-16 00:27:59 +00:00
{ " obfuscator " , mainEntryClickHouseObfuscator } ,
# endif
2020-09-07 03:22:47 +00:00
# if ENABLE_CLICKHOUSE_GIT_IMPORT
{ " git-import " , mainEntryClickHouseGitImport } ,
# endif
2021-05-12 10:39:07 +00:00
# if ENABLE_CLICKHOUSE_KEEPER
{ " keeper " , mainEntryClickHouseKeeper } ,
# endif
2021-06-17 16:32:50 +00:00
# if ENABLE_CLICKHOUSE_KEEPER_CONVERTER
{ " keeper-converter " , mainEntryClickHouseKeeperConverter } ,
# endif
2020-08-08 18:38:34 +00:00
# if ENABLE_CLICKHOUSE_INSTALL
{ " install " , mainEntryClickHouseInstall } ,
2020-08-08 20:42:10 +00:00
{ " start " , mainEntryClickHouseStart } ,
{ " stop " , mainEntryClickHouseStop } ,
{ " status " , mainEntryClickHouseStatus } ,
{ " restart " , mainEntryClickHouseRestart } ,
2021-06-18 11:21:05 +00:00
# endif
2021-08-28 20:21:05 +00:00
# if ENABLE_CLICKHOUSE_STATIC_FILES_DISK_UPLOADER
{ " static-files-disk-uploader " , mainEntryClickHouseStaticFilesDiskUploader } ,
2020-08-08 18:38:34 +00:00
# endif
2021-01-07 02:56:57 +00:00
{ " hash-binary " , mainEntryClickHouseHashBinary } ,
2017-09-20 13:41:13 +00:00
} ;
2017-12-02 02:47:12 +00:00
int printHelp ( int , char * * )
2017-09-20 13:41:13 +00:00
{
std : : cerr < < " Use one of the following commands: " < < std : : endl ;
for ( auto & application : clickhouse_applications )
std : : cerr < < " clickhouse " < < application . first < < " [args] " < < std : : endl ;
return - 1 ;
2018-08-26 01:14:00 +00:00
}
2017-09-20 13:41:13 +00:00
bool isClickhouseApp ( const std : : string & app_suffix , std : : vector < char * > & argv )
{
/// Use app if the first arg 'app' is passed (the arg should be quietly removed)
if ( argv . size ( ) > = 2 )
2017-04-01 07:20:54 +00:00
{
2017-09-20 13:41:13 +00:00
auto first_arg = argv . begin ( ) + 1 ;
2016-10-31 19:54:49 +00:00
2017-09-20 13:41:13 +00:00
/// 'clickhouse --client ...' and 'clickhouse client ...' are Ok
if ( * first_arg = = " -- " + app_suffix | | * first_arg = = app_suffix )
{
argv . erase ( first_arg ) ;
return true ;
}
}
2016-10-25 12:14:27 +00:00
2017-04-01 07:20:54 +00:00
/// Use app if clickhouse binary is run through symbolic link with name clickhouse-app
2017-09-20 13:41:13 +00:00
std : : string app_name = " clickhouse- " + app_suffix ;
return ! argv . empty ( ) & & ( app_name = = argv [ 0 ] | | endsWith ( argv [ 0 ] , " / " + app_name ) ) ;
}
2021-10-07 18:01:36 +00:00
# endif
2016-10-30 18:02:56 +00:00
2020-03-26 10:33:53 +00:00
enum class InstructionFail
{
NONE = 0 ,
SSE3 = 1 ,
SSSE3 = 2 ,
SSE4_1 = 3 ,
SSE4_2 = 4 ,
2020-05-24 16:39:31 +00:00
POPCNT = 5 ,
AVX = 6 ,
AVX2 = 7 ,
AVX512 = 8
2020-03-26 10:33:53 +00:00
} ;
2021-06-02 04:48:31 +00:00
auto instructionFailToString ( InstructionFail fail )
2020-03-26 10:33:53 +00:00
{
switch ( fail )
{
2021-06-02 04:48:31 +00:00
# define ret(x) return std::make_tuple(STDERR_FILENO, x, ARRAY_SIZE(x) - 1)
2020-03-26 10:33:53 +00:00
case InstructionFail : : NONE :
2020-10-04 08:24:36 +00:00
ret ( " NONE " ) ;
2020-03-26 10:33:53 +00:00
case InstructionFail : : SSE3 :
2020-10-04 08:24:36 +00:00
ret ( " SSE3 " ) ;
2020-03-26 10:33:53 +00:00
case InstructionFail : : SSSE3 :
2020-10-04 08:24:36 +00:00
ret ( " SSSE3 " ) ;
2020-03-26 10:33:53 +00:00
case InstructionFail : : SSE4_1 :
2020-10-04 08:24:36 +00:00
ret ( " SSE4.1 " ) ;
2020-03-26 10:33:53 +00:00
case InstructionFail : : SSE4_2 :
2020-10-04 08:24:36 +00:00
ret ( " SSE4.2 " ) ;
2020-05-24 16:39:31 +00:00
case InstructionFail : : POPCNT :
2020-10-04 08:24:36 +00:00
ret ( " POPCNT " ) ;
2020-03-26 10:33:53 +00:00
case InstructionFail : : AVX :
2020-10-04 08:24:36 +00:00
ret ( " AVX " ) ;
2020-03-26 10:33:53 +00:00
case InstructionFail : : AVX2 :
2020-10-04 08:24:36 +00:00
ret ( " AVX2 " ) ;
2020-03-26 10:33:53 +00:00
case InstructionFail : : AVX512 :
2020-10-04 08:24:36 +00:00
ret ( " AVX512 " ) ;
2020-03-26 10:33:53 +00:00
}
__builtin_unreachable ( ) ;
}
sigjmp_buf jmpbuf ;
2020-03-26 16:58:50 +00:00
[[noreturn]] void sigIllCheckHandler ( int , siginfo_t * , void * )
2020-03-26 10:33:53 +00:00
{
siglongjmp ( jmpbuf , 1 ) ;
}
2020-03-27 08:14:20 +00:00
/// Check if necessary SSE extensions are available by trying to execute some sse instructions.
2020-03-26 10:33:53 +00:00
/// If instruction is unavailable, SIGILL will be sent by kernel.
void checkRequiredInstructionsImpl ( volatile InstructionFail & fail )
{
2020-03-26 16:58:50 +00:00
# if defined(__SSE3__)
2020-03-26 10:33:53 +00:00
fail = InstructionFail : : SSE3 ;
__asm__ volatile ( " addsubpd %%xmm0, %%xmm0 " : : : " xmm0 " ) ;
# endif
2020-03-26 16:58:50 +00:00
# if defined(__SSSE3__)
2020-03-26 10:33:53 +00:00
fail = InstructionFail : : SSSE3 ;
__asm__ volatile ( " pabsw %%xmm0, %%xmm0 " : : : " xmm0 " ) ;
# endif
2020-03-26 16:58:50 +00:00
# if defined(__SSE4_1__)
2020-03-26 10:33:53 +00:00
fail = InstructionFail : : SSE4_1 ;
__asm__ volatile ( " pmaxud %%xmm0, %%xmm0 " : : : " xmm0 " ) ;
# endif
2020-03-26 16:58:50 +00:00
# if defined(__SSE4_2__)
2020-03-26 10:33:53 +00:00
fail = InstructionFail : : SSE4_2 ;
__asm__ volatile ( " pcmpgtq %%xmm0, %%xmm0 " : : : " xmm0 " ) ;
# endif
2020-05-24 16:39:31 +00:00
/// Defined by -msse4.2
# if defined(__POPCNT__)
fail = InstructionFail : : POPCNT ;
{
uint64_t a = 0 ;
uint64_t b = 0 ;
2020-05-27 17:23:09 +00:00
__asm__ volatile ( " popcnt %1, %0 " : " =r " ( a ) : " r " ( b ) : ) ;
2020-05-24 16:39:31 +00:00
}
# endif
2020-03-26 16:58:50 +00:00
# if defined(__AVX__)
2020-03-26 10:33:53 +00:00
fail = InstructionFail : : AVX ;
__asm__ volatile ( " vaddpd %%ymm0, %%ymm0, %%ymm0 " : : : " ymm0 " ) ;
# endif
2020-03-26 16:58:50 +00:00
# if defined(__AVX2__)
2020-03-26 10:33:53 +00:00
fail = InstructionFail : : AVX2 ;
__asm__ volatile ( " vpabsw %%ymm0, %%ymm0 " : : : " ymm0 " ) ;
# endif
2020-03-26 16:58:50 +00:00
# if defined(__AVX512__)
2020-03-26 10:33:53 +00:00
fail = InstructionFail : : AVX512 ;
__asm__ volatile ( " vpabsw %%zmm0, %%zmm0 " : : : " zmm0 " ) ;
# endif
fail = InstructionFail : : NONE ;
}
2020-10-04 08:24:36 +00:00
/// Macros to avoid using strlen(), since it may fail if SSE is not supported.
2020-10-05 06:28:52 +00:00
# define writeError(data) do \
{ \
static_assert ( __builtin_constant_p ( data ) ) ; \
2021-06-02 04:48:31 +00:00
if ( ! writeRetry ( STDERR_FILENO , data , ARRAY_SIZE ( data ) - 1 ) ) \
_Exit ( 1 ) ; \
2020-10-05 06:28:52 +00:00
} while ( false )
2020-03-26 17:53:57 +00:00
/// Check SSE and others instructions availability. Calls exit on fail.
/// This function must be called as early as possible, even before main, because static initializers may use unavailable instructions.
2020-03-26 10:33:53 +00:00
void checkRequiredInstructions ( )
{
struct sigaction sa { } ;
struct sigaction sa_old { } ;
sa . sa_sigaction = sigIllCheckHandler ;
sa . sa_flags = SA_SIGINFO ;
auto signal = SIGILL ;
if ( sigemptyset ( & sa . sa_mask ) ! = 0
| | sigaddset ( & sa . sa_mask , signal ) ! = 0
| | sigaction ( signal , & sa , & sa_old ) ! = 0 )
{
2020-03-26 17:53:57 +00:00
/// You may wonder about strlen.
/// Typical implementation of strlen is using SSE4.2 or AVX2.
/// But this is not the case because it's compiler builtin and is executed at compile time.
2020-10-03 22:38:16 +00:00
writeError ( " Can not set signal handler \n " ) ;
2020-03-26 17:53:57 +00:00
_Exit ( 1 ) ;
2020-03-26 10:33:53 +00:00
}
volatile InstructionFail fail = InstructionFail : : NONE ;
if ( sigsetjmp ( jmpbuf , 1 ) )
{
2020-10-03 22:38:16 +00:00
writeError ( " Instruction check fail. The CPU does not support " ) ;
2021-06-02 04:48:31 +00:00
if ( ! std : : apply ( writeRetry , instructionFailToString ( fail ) ) )
_Exit ( 1 ) ;
2020-10-03 22:38:16 +00:00
writeError ( " instruction set. \n " ) ;
2020-03-26 17:53:57 +00:00
_Exit ( 1 ) ;
2020-03-26 10:33:53 +00:00
}
checkRequiredInstructionsImpl ( fail ) ;
if ( sigaction ( signal , & sa_old , nullptr ) )
{
2020-10-03 22:38:16 +00:00
writeError ( " Can not set signal handler \n " ) ;
2020-03-26 17:53:57 +00:00
_Exit ( 1 ) ;
2020-03-26 10:33:53 +00:00
}
}
2020-10-03 22:38:16 +00:00
struct Checker
{
Checker ( )
{
2020-10-03 23:01:40 +00:00
checkRequiredInstructions ( ) ;
2020-10-03 22:38:16 +00:00
}
2021-11-25 23:03:04 +00:00
} checker
# ifndef __APPLE__
__attribute__ ( ( init_priority ( 101 ) ) ) /// Run before other static initializers.
# endif
;
2020-03-26 17:53:57 +00:00
2022-04-16 22:09:20 +00:00
/// ClickHouse can drop privileges at startup. It is controlled by environment variables.
void setUserAndGroup ( )
{
using namespace DB ;
static constexpr size_t buf_size = 16384 ; /// Linux man page says it is enough. Nevertheless, we will check if it's not enough and throw.
std : : unique_ptr < char [ ] > buf ( new char [ buf_size ] ) ;
const char * env_uid = getenv ( " CLICKHOUSE_SETUID " ) ;
if ( env_uid & & env_uid [ 0 ] )
{
/// Is it numeric id or name?
uid_t uid = 0 ;
if ( ! tryParse ( uid , env_uid ) )
{
passwd entry { } ;
passwd * result { } ;
if ( 0 ! = getpwnam_r ( env_uid , & entry , buf , buf_size , & result ) )
throwFromErrno ( fmt : : format ( " Cannot do 'getpwnam_r' to obtain uid from user name, specified in the CLICKHOUSE_SETUID environment variable ({}) " , env_uid ) , ErrorCodes : : SYSTEM_ERROR ) ;
if ( ! result )
throw Exception ( " User {} specified in the CLICKHOUSE_SETUID environment variable is not found in the system " , ErrorCodes : : BAD_ARGUMENTS ) ;
uid = entry . pw_uid ;
}
if ( uid = = 0 )
throw Exception ( " User specified in the CLICKHOUSE_SETUID environment variable has id 0, but dropping privileges to uid 0 does not make sense " , ErrorCodes : : BAD_ARGUMENTS ) ;
if ( 0 ! = setuid ( uid ) )
throwFromErrno ( fmt : : format ( " Cannot do 'setuid' to user, specified in the CLICKHOUSE_SETUID environment variable ({}) " , env_uid ) , ErrorCodes : : SYSTEM_ERROR ) ;
}
const char * env_gid = getenv ( " CLICKHOUSE_SETGID " ) ;
if ( env_gid & & env_gid [ 0 ] )
{
gid_t gid = 0 ;
if ( ! tryParse ( gid , env_gid ) )
{
std : : vector < char > buf ( buf_size ) ;
group entry { } ;
group * result { } ;
if ( 0 ! = getgrnam_r ( env_gid , & entry , buf , buf_size , & result ) )
throwFromErrno ( fmt : : format ( " Cannot do 'getgrnam_r' to obtain gid from group name, specified in the CLICKHOUSE_SETGID environment variable ({}) " , env_gid ) , ErrorCodes : : SYSTEM_ERROR ) ;
if ( ! result )
throw Exception ( " Group {} specified in the CLICKHOUSE_SETGID environment variable is not found in the system " , ErrorCodes : : BAD_ARGUMENTS ) ;
gid = entry . gr_gid ;
}
if ( gid = = 0 )
throw Exception ( " Group specified in the CLICKHOUSE_SETGID environment variable has id 0, but dropping privileges to gid 0 does not make sense " , ErrorCodes : : BAD_ARGUMENTS ) ;
if ( 0 ! = setgid ( gid ) )
throwFromErrno ( fmt : : format ( " Cannot do 'setgid' to user, specified in the CLICKHOUSE_SETGID environment variable ({}) " , env_gid ) , ErrorCodes : : SYSTEM_ERROR ) ;
}
}
2016-10-31 19:54:49 +00:00
}
2019-08-28 17:13:29 +00:00
/// This allows to implement assert to forbid initialization of a class in static constructors.
/// Usage:
///
/// extern bool inside_main;
/// class C { C() { assert(inside_main); } };
2021-10-07 18:01:36 +00:00
# ifndef FUZZING_MODE
2019-08-28 17:13:29 +00:00
bool inside_main = false ;
2021-10-07 18:01:36 +00:00
# else
bool inside_main = true ;
# endif
2019-08-28 17:13:29 +00:00
2021-12-06 18:27:06 +00:00
# if !defined(FUZZING_MODE)
2016-10-31 19:54:49 +00:00
int main ( int argc_ , char * * argv_ )
{
2019-08-28 17:13:29 +00:00
inside_main = true ;
SCOPE_EXIT ( { inside_main = false ; } ) ;
2022-04-16 22:09:20 +00:00
/// Drop privileges if needed.
setUserAndGroup ( ) ;
2019-03-12 19:30:59 +00:00
/// Reset new handler to default (that throws std::bad_alloc)
/// It is needed because LLVM library clobbers it.
std : : set_new_handler ( nullptr ) ;
2019-07-24 15:26:23 +00:00
/// PHDR cache is required for query profiler to work reliably
2019-07-26 00:54:48 +00:00
/// It also speed up exception handling, but exceptions from dynamically loaded libraries (dlopen)
/// will work only after additional call of this function.
2019-07-25 19:54:16 +00:00
updatePHDRCache ( ) ;
2019-07-24 15:26:23 +00:00
2017-04-01 07:20:54 +00:00
std : : vector < char * > argv ( argv_ , argv_ + argc_ ) ;
2016-10-31 19:54:49 +00:00
2017-09-20 13:41:13 +00:00
/// Print a basic help if nothing was matched
MainFunc main_func = printHelp ;
for ( auto & application : clickhouse_applications )
{
if ( isClickhouseApp ( application . first , argv ) )
{
main_func = application . second ;
break ;
}
}
2016-10-28 17:38:32 +00:00
2017-04-01 07:20:54 +00:00
return main_func ( static_cast < int > ( argv . size ( ) ) , argv . data ( ) ) ;
2016-10-25 12:14:27 +00:00
}
2021-10-07 18:01:36 +00:00
# endif