~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/drizzled.cc

  • Committer: Monty Taylor
  • Date: 2010-02-16 07:05:28 UTC
  • mto: (1471.3.2 drizzled-as-lib)
  • mto: This revision was merged to the branch mainline in revision 1479.
  • Revision ID: mordred@inaugust.com-20100216070528-psvrbp9r3ue4tsh8
Changed build to build the almost all of drizzle into libdrizzled and then
have a small main.cc program which links in libdrizzled. This will allow us
to easily track exported API symbols and symbol changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
#include "drizzled/internal/my_sys.h"
32
32
#include "drizzled/internal/my_bit.h"
33
33
#include <drizzled/my_hash.h>
34
 
#include <drizzled/stacktrace.h>
35
34
#include <drizzled/error.h>
36
35
#include <drizzled/errmsg_print.h>
37
36
#include <drizzled/tztime.h>
51
50
#include "drizzled/session_list.h"
52
51
#include "drizzled/charset.h"
53
52
#include "plugin/myisam/myisam.h"
 
53
#include "drizzled/drizzled.h"
54
54
 
55
55
#include <google/protobuf/stubs/common.h>
56
56
 
82
82
#include <pwd.h>                                // For getpwent
83
83
#include <grp.h>
84
84
 
85
 
#include <sys/resource.h>
86
 
 
87
85
#ifdef HAVE_SELECT_H
88
86
#  include <select.h>
89
87
#endif
188
186
/*
189
187
  Used with --help for detailed option
190
188
*/
191
 
static bool opt_help= false;
192
 
static bool opt_help_extended= false;
 
189
bool opt_help= false;
 
190
bool opt_help_extended= false;
193
191
 
194
192
arg_cmp_func Arg_comparator::comparator_matrix[5][2] =
195
193
{{&Arg_comparator::compare_string,     &Arg_comparator::compare_e_string},
200
198
 
201
199
/* static variables */
202
200
 
203
 
static bool volatile select_thread_in_use;
204
 
static bool volatile ready_to_exit;
205
201
static bool opt_debugging= 0;
206
202
static uint32_t wake_thread;
207
 
static uint32_t killed_threads;
208
 
static char *drizzled_user, *drizzled_chroot;
 
203
static char *drizzled_chroot;
209
204
static char *language_ptr;
210
205
static const char *default_character_set_name;
211
206
static const char *character_set_filesystem_name;
216
211
 
217
212
/* Global variables */
218
213
 
 
214
bool volatile ready_to_exit;
 
215
char *drizzled_user;
 
216
bool volatile select_thread_in_use;
219
217
bool volatile abort_loop;
220
218
bool volatile shutdown_in_progress;
221
219
uint32_t max_used_connections;
232
230
 
233
231
char* opt_secure_file_priv= 0;
234
232
 
235
 
static bool calling_initgroups= false; /**< Used in SIGSEGV handler. */
 
233
bool calling_initgroups= false; /**< Used in SIGSEGV handler. */
236
234
 
237
235
uint32_t drizzled_bind_timeout;
238
236
std::bitset<12> test_flags;
344
342
 
345
343
/* Static variables */
346
344
 
347
 
static bool segfaulted;
348
345
#ifdef HAVE_STACK_TRACE_ON_SEGV
349
346
static bool opt_do_pstack;
350
347
#endif /* HAVE_STACK_TRACE_ON_SEGV */
353
350
static int defaults_argc;
354
351
static char **defaults_argv;
355
352
 
356
 
struct passwd *user_info;
357
 
static pthread_t select_thread;
358
 
static uint32_t thr_kill_signal;
 
353
passwd *user_info;
359
354
 
360
355
/**
361
356
  Number of currently active user connections. The variable is protected by
379
374
static const char *get_relative_path(const char *path);
380
375
static void fix_paths(string &progname);
381
376
extern "C" pthread_handler_t handle_slave(void *arg);
382
 
static void clean_up(bool print_message);
383
377
 
384
378
static void usage(void);
385
 
static void clean_up_mutexes(void);
386
379
void close_connections(void);
387
380
 
388
381
/****************************************************************************
467
460
  }
468
461
}
469
462
 
470
 
extern "C" void print_signal_warning(int sig);
471
 
 
472
 
extern "C" void print_signal_warning(int sig)
473
 
{
474
 
  if (global_system_variables.log_warnings)
475
 
    errmsg_printf(ERRMSG_LVL_WARN, _("Got signal %d from thread %"PRIu64),
476
 
                  sig, global_thread_id);
477
 
#ifndef HAVE_BSD_SIGNALS
478
 
  my_sigset(sig,print_signal_warning);          /* int. thread system calls */
479
 
#endif
480
 
  if (sig == SIGALRM)
481
 
    alarm(2);                                   /* reschedule alarm */
482
 
}
483
 
 
484
463
/**
485
464
  cleanup all memory and end program nicely.
486
465
 
517
496
}
518
497
 
519
498
 
520
 
static void clean_up(bool print_message)
 
499
void clean_up(bool print_message)
521
500
{
522
501
  if (cleanup_done++)
523
502
    return;
566
545
} /* clean_up */
567
546
 
568
547
 
569
 
static void clean_up_mutexes()
 
548
void clean_up_mutexes()
570
549
{
571
550
  (void) pthread_mutex_destroy(&LOCK_create_db);
572
551
  (void) pthread_mutex_destroy(&LOCK_open);
584
563
 
585
564
/* Change to run as another user if started with --user */
586
565
 
587
 
static struct passwd *check_user(const char *user)
 
566
passwd *check_user(const char *user)
588
567
{
589
 
  struct passwd *tmp_user_info;
 
568
  passwd *tmp_user_info;
590
569
  uid_t user_id= geteuid();
591
570
 
592
571
  // Don't bother if we aren't superuser
644
623
 
645
624
}
646
625
 
647
 
static void set_user(const char *user, struct passwd *user_info_arg)
 
626
void set_user(const char *user, passwd *user_info_arg)
648
627
{
649
628
  assert(user_info_arg != 0);
650
629
  /*
669
648
}
670
649
 
671
650
 
 
651
 
672
652
/** Change root user if started with @c --chroot . */
673
653
static void set_root(const char *path)
674
654
{
679
659
  }
680
660
}
681
661
 
682
 
extern "C" void end_thread_signal(int );
683
 
 
684
 
/** Called when a thread is aborted. */
685
 
extern "C" void end_thread_signal(int )
686
 
{
687
 
  Session *session=current_session;
688
 
  if (session)
689
 
  {
690
 
    statistic_increment(killed_threads, &LOCK_status);
691
 
    session->scheduler->killSessionNow(session);
692
 
    DRIZZLE_CONNECTION_DONE(session->thread_id);
693
 
  }
694
 
  return;
695
 
}
696
 
 
697
662
 
698
663
/*
699
664
  Unlink session from global list of available connections and free session
741
706
}
742
707
#endif
743
708
 
744
 
#if defined(BACKTRACE_DEMANGLE)
745
 
#include <cxxabi.h>
746
 
extern "C" char *my_demangle(const char *mangled_name, int *status)
747
 
{
748
 
  return abi::__cxa_demangle(mangled_name, NULL, NULL, status);
749
 
}
750
 
#endif
751
 
 
752
 
extern "C" void handle_segfault(int sig);
753
 
 
754
 
extern "C" void handle_segfault(int sig)
755
 
{
756
 
  time_t curr_time;
757
 
  struct tm tm;
758
 
 
759
 
  /*
760
 
    Strictly speaking, one needs a mutex here
761
 
    but since we have got SIGSEGV already, things are a mess
762
 
    so not having the mutex is not as bad as possibly using a buggy
763
 
    mutex - so we keep things simple
764
 
  */
765
 
  if (segfaulted)
766
 
  {
767
 
    fprintf(stderr, _("Fatal signal %d while backtracing\n"), sig);
768
 
    exit(1);
769
 
  }
770
 
 
771
 
  segfaulted = 1;
772
 
 
773
 
  curr_time= time(NULL);
774
 
  if(curr_time == (time_t)-1)
775
 
  {
776
 
    fprintf(stderr, "Fetal: time() call failed\n");
777
 
    exit(1);
778
 
  }
779
 
 
780
 
  localtime_r(&curr_time, &tm);
781
 
  
782
 
  fprintf(stderr,"%02d%02d%02d %2d:%02d:%02d - drizzled got signal %d;\n"
783
 
          "This could be because you hit a bug. It is also possible that "
784
 
          "this binary\n or one of the libraries it was linked against is "
785
 
          "corrupt, improperly built,\n or misconfigured. This error can "
786
 
          "also be caused by malfunctioning hardware.\n",
787
 
          tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
788
 
          tm.tm_hour, tm.tm_min, tm.tm_sec,
789
 
          sig);
790
 
  fprintf(stderr, _("We will try our best to scrape up some info that "
791
 
                    "will hopefully help diagnose\n"
792
 
                    "the problem, but since we have already crashed, "
793
 
                    "something is definitely wrong\nand this may fail.\n\n"));
794
 
  fprintf(stderr, "key_buffer_size=%u\n",
795
 
          (uint32_t) dflt_key_cache->key_cache_mem_size);
796
 
  fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size);
797
 
  fprintf(stderr, "max_used_connections=%u\n", max_used_connections);
798
 
  fprintf(stderr, "connection_count=%u\n", uint32_t(connection_count));
799
 
  fprintf(stderr, _("It is possible that drizzled could use up to \n"
800
 
                    "key_buffer_size + (read_buffer_size + "
801
 
                    "sort_buffer_size)*thread_count\n"
802
 
                    "bytes of memory\n"
803
 
                    "Hope that's ok; if not, decrease some variables in the "
804
 
                    "equation.\n\n"));
805
 
 
806
 
#ifdef HAVE_STACKTRACE
807
 
  Session *session= current_session;
808
 
 
809
 
  if (! (test_flags.test(TEST_NO_STACKTRACE)))
810
 
  {
811
 
    fprintf(stderr,"session: 0x%lx\n",(long) session);
812
 
    fprintf(stderr,_("Attempting backtrace. You can use the following "
813
 
                     "information to find out\n"
814
 
                     "where drizzled died. If you see no messages after this, "
815
 
                     "something went\n"
816
 
                     "terribly wrong...\n"));
817
 
    print_stacktrace(session ? (unsigned char*) session->thread_stack : (unsigned char*) 0,
818
 
                     my_thread_stack_size);
819
 
  }
820
 
  if (session)
821
 
  {
822
 
    const char *kreason= "UNKNOWN";
823
 
    switch (session->killed) {
824
 
    case Session::NOT_KILLED:
825
 
      kreason= "NOT_KILLED";
826
 
      break;
827
 
    case Session::KILL_BAD_DATA:
828
 
      kreason= "KILL_BAD_DATA";
829
 
      break;
830
 
    case Session::KILL_CONNECTION:
831
 
      kreason= "KILL_CONNECTION";
832
 
      break;
833
 
    case Session::KILL_QUERY:
834
 
      kreason= "KILL_QUERY";
835
 
      break;
836
 
    case Session::KILLED_NO_VALUE:
837
 
      kreason= "KILLED_NO_VALUE";
838
 
      break;
839
 
    }
840
 
    fprintf(stderr, _("Trying to get some variables.\n"
841
 
                      "Some pointers may be invalid and cause the "
842
 
                      "dump to abort...\n"));
843
 
    safe_print_str("session->query", session->query, 1024);
844
 
    fprintf(stderr, "session->thread_id=%"PRIu32"\n", (uint32_t) session->thread_id);
845
 
    fprintf(stderr, "session->killed=%s\n", kreason);
846
 
  }
847
 
  fflush(stderr);
848
 
#endif /* HAVE_STACKTRACE */
849
 
 
850
 
  if (calling_initgroups)
851
 
    fprintf(stderr, _("\nThis crash occurred while the server was calling "
852
 
                      "initgroups(). This is\n"
853
 
                      "often due to the use of a drizzled that is statically "
854
 
                      "linked against glibc\n"
855
 
                      "and configured to use LDAP in /etc/nsswitch.conf. "
856
 
                      "You will need to either\n"
857
 
                      "upgrade to a version of glibc that does not have this "
858
 
                      "problem (2.3.4 or\n"
859
 
                      "later when used with nscd), disable LDAP in your "
860
 
                      "nsswitch.conf, or use a\n"
861
 
                      "drizzled that is not statically linked.\n"));
862
 
 
863
 
  if (internal::thd_lib_detected == THD_LIB_LT && !getenv("LD_ASSUME_KERNEL"))
864
 
    fprintf(stderr,
865
 
            _("\nYou are running a statically-linked LinuxThreads binary "
866
 
              "on an NPTL system.\n"
867
 
              "This can result in crashes on some distributions due "
868
 
              "to LT/NPTL conflicts.\n"
869
 
              "You should either build a dynamically-linked binary, or force "
870
 
              "LinuxThreads\n"
871
 
              "to be used with the LD_ASSUME_KERNEL environment variable. "
872
 
              "Please consult\n"
873
 
              "the documentation for your distribution on how to do that.\n"));
874
 
 
875
 
#ifdef HAVE_WRITE_CORE
876
 
  if (test_flags.test(TEST_CORE_ON_SIGNAL))
877
 
  {
878
 
    fprintf(stderr, _("Writing a core file\n"));
879
 
    fflush(stderr);
880
 
    write_core(sig);
881
 
  }
882
 
#endif
883
 
 
884
 
  exit(1);
885
 
}
 
709
 
886
710
 
887
711
#ifndef SA_RESETHAND
888
712
#define SA_RESETHAND 0
892
716
#endif
893
717
 
894
718
 
895
 
/**
896
 
  All global error messages are sent here where the first one is stored
897
 
  for the client.
898
 
*/
899
 
static void my_message_sql(uint32_t error, const char *str, myf MyFlags)
 
719
 
 
720
 
 
721
const char *load_default_groups[]= 
900
722
{
901
 
  Session *session;
902
 
  /*
903
 
    Put here following assertion when situation with EE_* error codes
904
 
    will be fixed
905
 
  */
906
 
  if ((session= current_session))
907
 
  {
908
 
    if (MyFlags & ME_FATALERROR)
909
 
      session->is_fatal_error= 1;
910
 
 
911
 
    /*
912
 
      TODO: There are two exceptions mechanism (Session and sp_rcontext),
913
 
      this could be improved by having a common stack of handlers.
914
 
    */
915
 
    if (session->handle_error(error, str,
916
 
                          DRIZZLE_ERROR::WARN_LEVEL_ERROR))
917
 
      return;;
918
 
 
919
 
    /*
920
 
      session->lex->current_select == 0 if lex structure is not inited
921
 
      (not query command (COM_QUERY))
922
 
    */
923
 
    if (! (session->lex->current_select &&
924
 
        session->lex->current_select->no_error && !session->is_fatal_error))
925
 
    {
926
 
      if (! session->main_da.is_error())            // Return only first message
927
 
      {
928
 
        if (error == 0)
929
 
          error= ER_UNKNOWN_ERROR;
930
 
        if (str == NULL)
931
 
          str= ER(error);
932
 
        session->main_da.set_error_status(error, str);
933
 
      }
934
 
    }
935
 
 
936
 
    if (!session->no_warnings_for_error && !session->is_fatal_error)
937
 
    {
938
 
      /*
939
 
        Suppress infinite recursion if there a memory allocation error
940
 
        inside push_warning.
941
 
      */
942
 
      session->no_warnings_for_error= true;
943
 
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error, str);
944
 
      session->no_warnings_for_error= false;
945
 
    }
946
 
  }
947
 
  if (!session || MyFlags & ME_NOREFRESH)
948
 
    errmsg_printf(ERRMSG_LVL_ERROR, "%s: %s",internal::my_progname,str);
949
 
}
950
 
 
951
 
 
952
 
static const char *load_default_groups[]= {
953
 
DRIZZLE_CONFIG_NAME, "server", 0, 0};
 
723
  DRIZZLE_CONFIG_NAME, "server", 0, 0
 
724
};
954
725
 
955
726
static int show_starttime(SHOW_VAR *var, char *buff)
956
727
{
1106
877
  {NULL, NULL, SHOW_LONGLONG}
1107
878
};
1108
879
 
1109
 
static int init_common_variables(const char *conf_file_name, int argc,
1110
 
                                 char **argv, const char **groups)
 
880
int init_common_variables(const char *conf_file_name, int argc,
 
881
                          char **argv, const char **groups)
1111
882
{
1112
883
  time_t curr_time;
1113
884
  umask(((~internal::my_umask) & 0666));
1257
1028
}
1258
1029
 
1259
1030
 
1260
 
static int init_server_components(plugin::Registry &plugins)
 
1031
int init_server_components(plugin::Registry &plugins)
1261
1032
{
1262
1033
  /*
1263
1034
    We need to call each of these following functions to ensure that
1867
1638
  drizzle_home[0]= pidfile_name[0]= 0;
1868
1639
  opt_tc_log_file= (char *)"tc.log";      // no hostname in tc_log file name !
1869
1640
  opt_secure_file_priv= 0;
1870
 
  segfaulted= 0;
1871
1641
  cleanup_done= 0;
1872
1642
  defaults_argc= 0;
1873
1643
  defaults_argv= 0;
2174
1944
      progdir.assign(progdir.substr(0, progdir.rfind(".libs/")));
2175
1945
    }
2176
1946
    string testfile(progdir);
2177
 
    testfile.append("drizzled.o");
 
1947
    testfile.append("drizzled.lo");
2178
1948
    struct stat testfile_stat;
2179
1949
    if (stat(testfile.c_str(), &testfile_stat))
2180
1950
    {
2181
 
      /* drizzled.o doesn't exist - we are not in a source dir.
 
1951
      /* drizzled.lo doesn't exist - we are not in a source dir.
2182
1952
       * Go on as usual
2183
1953
       */
2184
1954
      (void) internal::my_load_path(opt_plugin_dir, get_relative_path(PKGPLUGINDIR),
2247
2017
 
2248
2018
} /* namespace drizzled */
2249
2019
 
2250
 
using namespace drizzled;
2251
 
 
2252
 
 
2253
 
static void init_signals(void)
2254
 
{
2255
 
  sigset_t set;
2256
 
  struct sigaction sa;
2257
 
 
2258
 
  if (!(test_flags.test(TEST_NO_STACKTRACE) || 
2259
 
        test_flags.test(TEST_CORE_ON_SIGNAL)))
2260
 
  {
2261
 
    sa.sa_flags = SA_RESETHAND | SA_NODEFER;
2262
 
    sigemptyset(&sa.sa_mask);
2263
 
    sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
2264
 
 
2265
 
    init_stacktrace();
2266
 
    sa.sa_handler=handle_segfault;
2267
 
    sigaction(SIGSEGV, &sa, NULL);
2268
 
    sigaction(SIGABRT, &sa, NULL);
2269
 
#ifdef SIGBUS
2270
 
    sigaction(SIGBUS, &sa, NULL);
2271
 
#endif
2272
 
    sigaction(SIGILL, &sa, NULL);
2273
 
    sigaction(SIGFPE, &sa, NULL);
2274
 
  }
2275
 
 
2276
 
  if (test_flags.test(TEST_CORE_ON_SIGNAL))
2277
 
  {
2278
 
    /* Change limits so that we will get a core file */
2279
 
    struct rlimit rl;
2280
 
    rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
2281
 
    if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
2282
 
        errmsg_printf(ERRMSG_LVL_WARN,
2283
 
                      _("setrlimit could not change the size of core files "
2284
 
                        "to 'infinity';  We may not be able to generate a "
2285
 
                        "core file on signals"));
2286
 
  }
2287
 
  (void) sigemptyset(&set);
2288
 
  my_sigset(SIGPIPE,SIG_IGN);
2289
 
  sigaddset(&set,SIGPIPE);
2290
 
#ifndef IGNORE_SIGHUP_SIGQUIT
2291
 
  sigaddset(&set,SIGQUIT);
2292
 
  sigaddset(&set,SIGHUP);
2293
 
#endif
2294
 
  sigaddset(&set,SIGTERM);
2295
 
 
2296
 
  /* Fix signals if blocked by parents (can happen on Mac OS X) */
2297
 
  sigemptyset(&sa.sa_mask);
2298
 
  sa.sa_flags = 0;
2299
 
  sa.sa_handler = print_signal_warning;
2300
 
  sigaction(SIGTERM, &sa, (struct sigaction*) 0);
2301
 
  sa.sa_flags = 0;
2302
 
  sa.sa_handler = print_signal_warning;
2303
 
  sigaction(SIGHUP, &sa, (struct sigaction*) 0);
2304
 
#ifdef SIGTSTP
2305
 
  sigaddset(&set,SIGTSTP);
2306
 
#endif
2307
 
  if (test_flags.test(TEST_SIGINT))
2308
 
  {
2309
 
    my_sigset(thr_kill_signal, end_thread_signal);
2310
 
    // May be SIGINT
2311
 
    sigdelset(&set, thr_kill_signal);
2312
 
  }
2313
 
  else
2314
 
    sigaddset(&set,SIGINT);
2315
 
  sigprocmask(SIG_SETMASK,&set,NULL);
2316
 
  pthread_sigmask(SIG_SETMASK,&set,NULL);
2317
 
  return;;
2318
 
}
2319
 
 
2320
 
int main(int argc, char **argv)
2321
 
{
2322
 
#if defined(ENABLE_NLS)
2323
 
# if defined(HAVE_LOCALE_H)
2324
 
  setlocale(LC_ALL, "");
2325
 
# endif
2326
 
  bindtextdomain("drizzle", LOCALEDIR);
2327
 
  textdomain("drizzle");
2328
 
#endif
2329
 
 
2330
 
  plugin::Registry &plugins= plugin::Registry::singleton();
2331
 
  plugin::Client *client;
2332
 
  Session *session;
2333
 
 
2334
 
  MY_INIT(argv[0]);             // init my_sys library & pthreads
2335
 
  /* nothing should come before this line ^^^ */
2336
 
 
2337
 
  /* Set signal used to kill Drizzle */
2338
 
#if defined(SIGUSR2)
2339
 
  thr_kill_signal= internal::thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2;
2340
 
#else
2341
 
  thr_kill_signal= SIGINT;
2342
 
#endif
2343
 
 
2344
 
  if (init_common_variables(DRIZZLE_CONFIG_NAME,
2345
 
                            argc, argv, load_default_groups))
2346
 
    unireg_abort(1);                            // Will do exit
2347
 
 
2348
 
  init_signals();
2349
 
 
2350
 
 
2351
 
  select_thread=pthread_self();
2352
 
  select_thread_in_use=1;
2353
 
 
2354
 
  if (chdir(drizzle_real_data_home) && !opt_help)
2355
 
  {
2356
 
    errmsg_printf(ERRMSG_LVL_ERROR, _("Data directory %s does not exist\n"), drizzle_real_data_home);
2357
 
    unireg_abort(1);
2358
 
  }
2359
 
  drizzle_data_home= drizzle_data_home_buff;
2360
 
  drizzle_data_home[0]=FN_CURLIB;               // all paths are relative from here
2361
 
  drizzle_data_home[1]=0;
2362
 
  drizzle_data_home_len= 2;
2363
 
 
2364
 
  if ((user_info= check_user(drizzled_user)))
2365
 
  {
2366
 
    set_user(drizzled_user, user_info);
2367
 
  }
2368
 
 
2369
 
  if (server_id == 0)
2370
 
  {
2371
 
    server_id= 1;
2372
 
  }
2373
 
 
2374
 
  if (init_server_components(plugins))
2375
 
    unireg_abort(1);
2376
 
 
2377
 
  if (plugin::Listen::setup())
2378
 
    unireg_abort(1);
2379
 
 
2380
 
  /*
2381
 
    init signals & alarm
2382
 
    After this we can't quit by a simple unireg_abort
2383
 
  */
2384
 
  error_handler_hook= my_message_sql;
2385
 
 
2386
 
  if (drizzle_rm_tmp_tables() ||
2387
 
      my_tz_init((Session *)0, default_tz_name))
2388
 
  {
2389
 
    abort_loop= true;
2390
 
    select_thread_in_use=0;
2391
 
    (void) pthread_kill(signal_thread, SIGTERM);
2392
 
 
2393
 
    (void) unlink(pidfile_name);        // Not needed anymore
2394
 
 
2395
 
    exit(1);
2396
 
  }
2397
 
 
2398
 
  init_status_vars();
2399
 
 
2400
 
  errmsg_printf(ERRMSG_LVL_INFO, _(ER(ER_STARTUP)), internal::my_progname,
2401
 
                PANDORA_RELEASE_VERSION, COMPILATION_COMMENT);
2402
 
 
2403
 
 
2404
 
  /* Listen for new connections and start new session for each connection
2405
 
     accepted. The listen.getClient() method will return NULL when the server
2406
 
     should be shutdown. */
2407
 
  while ((client= plugin::Listen::getClient()) != NULL)
2408
 
  {
2409
 
    if (!(session= new Session(client)))
2410
 
    {
2411
 
      delete client;
2412
 
      continue;
2413
 
    }
2414
 
 
2415
 
    /* If we error on creation we drop the connection and delete the session. */
2416
 
    if (session->schedule())
2417
 
      Session::unlink(session);
2418
 
  }
2419
 
 
2420
 
  /* (void) pthread_attr_destroy(&connection_attrib); */
2421
 
 
2422
 
 
2423
 
  (void) pthread_mutex_lock(&LOCK_thread_count);
2424
 
  select_thread_in_use=0;                       // For close_connections
2425
 
  (void) pthread_mutex_unlock(&LOCK_thread_count);
2426
 
  (void) pthread_cond_broadcast(&COND_thread_count);
2427
 
 
2428
 
  /* Wait until cleanup is done */
2429
 
  (void) pthread_mutex_lock(&LOCK_thread_count);
2430
 
  while (!ready_to_exit)
2431
 
    pthread_cond_wait(&COND_server_end,&LOCK_thread_count);
2432
 
  (void) pthread_mutex_unlock(&LOCK_thread_count);
2433
 
 
2434
 
  clean_up(1);
2435
 
  plugin::Registry::shutdown();
2436
 
  clean_up_mutexes();
2437
 
  internal::my_end();
2438
 
  return 0;
2439
 
}
2440