detach.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /*
  13. * Copyright (c) 1990, 1994 Regents of the University of Michigan.
  14. * All rights reserved.
  15. *
  16. * Redistribution and use in source and binary forms are permitted
  17. * provided that this notice is preserved and that due credit is given
  18. * to the University of Michigan at Ann Arbor. The name of the University
  19. * may not be used to endorse or promote products derived from this
  20. * software without specific prior written permission. This software
  21. * is provided ``as is'' without express or implied warranty.
  22. */
  23. #include <stdio.h>
  24. #include <sys/types.h>
  25. #ifdef SVR4
  26. #include <sys/stat.h>
  27. #endif /* svr4 */
  28. #include <fcntl.h>
  29. #include <errno.h>
  30. #include <sys/file.h>
  31. #include <sys/ioctl.h>
  32. #include <sys/resource.h>
  33. #include <signal.h>
  34. #ifdef LINUX
  35. #undef CTIME
  36. #endif
  37. #include "slap.h"
  38. #include "fe.h"
  39. #if defined(USE_SYSCONF) || defined(LINUX)
  40. #include <unistd.h>
  41. #endif /* USE_SYSCONF */
  42. int
  43. detach( int slapd_exemode, int importexport_encrypt,
  44. int s_port, daemon_ports_t *ports_info )
  45. {
  46. int i, sd;
  47. char *workingdir = 0;
  48. char *errorlog = 0;
  49. char *ptr = 0;
  50. char errorbuf[BUFSIZ];
  51. extern char *config_get_errorlog(void);
  52. if ( should_detach ) {
  53. for ( i = 0; i < 5; i++ ) {
  54. #if defined( sunos5 )
  55. switch ( fork1() ) {
  56. #else
  57. switch ( fork() ) {
  58. #endif
  59. case -1:
  60. sleep( 5 );
  61. continue;
  62. case 0:
  63. break;
  64. default:
  65. _exit( 0 );
  66. }
  67. break;
  68. }
  69. /* call this right after the fork, but before closing stdin */
  70. if (slapd_do_all_nss_ssl_init(slapd_exemode, importexport_encrypt,
  71. s_port, ports_info)) {
  72. return 1;
  73. }
  74. workingdir = config_get_workingdir();
  75. if ( NULL == workingdir ) {
  76. errorlog = config_get_errorlog();
  77. if ( NULL == errorlog ) {
  78. (void) chdir( "/" );
  79. } else {
  80. if ((ptr = strrchr(errorlog, '/')) ||
  81. (ptr = strrchr(errorlog, '\\'))) {
  82. *ptr = 0;
  83. }
  84. (void) chdir( errorlog );
  85. config_set_workingdir(CONFIG_WORKINGDIR_ATTRIBUTE, errorlog, errorbuf, 1);
  86. slapi_ch_free_string(&errorlog);
  87. }
  88. } else {
  89. /* calling config_set_workingdir to check for validity of directory, don't apply */
  90. if (config_set_workingdir(CONFIG_WORKINGDIR_ATTRIBUTE, workingdir, errorbuf, 0) == LDAP_OPERATIONS_ERROR) {
  91. return 1;
  92. }
  93. (void) chdir( workingdir );
  94. slapi_ch_free_string(&workingdir);
  95. }
  96. if ( (sd = open( "/dev/null", O_RDWR )) == -1 ) {
  97. perror( "/dev/null" );
  98. return 1;
  99. }
  100. (void) dup2( sd, 0 );
  101. (void) dup2( sd, 1 );
  102. (void) dup2( sd, 2 );
  103. close( sd );
  104. #ifdef USE_SETSID
  105. setsid();
  106. #else /* USE_SETSID */
  107. if ( (sd = open( "/dev/tty", O_RDWR )) != -1 ) {
  108. (void) ioctl( sd, TIOCNOTTY, NULL );
  109. (void) close( sd );
  110. }
  111. #endif /* USE_SETSID */
  112. g_set_detached(1);
  113. } else { /* not detaching - call nss/ssl init */
  114. if (slapd_do_all_nss_ssl_init(slapd_exemode, importexport_encrypt,
  115. s_port, ports_info)) {
  116. return 1;
  117. }
  118. }
  119. (void) SIGNAL( SIGPIPE, SIG_IGN );
  120. return 0;
  121. }
  122. /*
  123. * close all open files except stdin/out/err
  124. */
  125. void
  126. close_all_files()
  127. {
  128. int i, nbits;
  129. #ifdef USE_SYSCONF
  130. nbits = sysconf( _SC_OPEN_MAX );
  131. #else /* USE_SYSCONF */
  132. nbits = getdtablesize();
  133. #endif /* USE_SYSCONF */
  134. for ( i = 3; i < nbits; i++ ) {
  135. close( i );
  136. }
  137. }
  138. static void raise_process_fd_limits(void)
  139. {
  140. struct rlimit rl, setrl;
  141. RLIM_TYPE curlim;
  142. slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
  143. if ( slapdFrontendConfig->maxdescriptors < 0 ) {
  144. return;
  145. }
  146. /*
  147. * Try to set our file descriptor limit. Our basic strategy is:
  148. * 1) Try to set the soft limit and the hard limit if
  149. * necessary to match our maxdescriptors value.
  150. * 2) If that fails and our soft limit is less than our hard
  151. * limit, we try to raise it to match the hard.
  152. */
  153. if ( getrlimit( RLIMIT_NOFILE, &rl ) != 0 ) {
  154. int oserr = errno;
  155. LDAPDebug( LDAP_DEBUG_ANY,
  156. "getrlimit of descriptor limit failed - error %d (%s)\n",
  157. oserr, slapd_system_strerror( oserr ), 0 );
  158. return;
  159. }
  160. if ( rl.rlim_cur == slapdFrontendConfig->maxdescriptors ) { /* already correct */
  161. return;
  162. }
  163. curlim = rl.rlim_cur;
  164. setrl = rl; /* struct copy */
  165. setrl.rlim_cur = slapdFrontendConfig->maxdescriptors;
  166. /* don't lower the hard limit as it's irreversible */
  167. if (setrl.rlim_cur > setrl.rlim_max) {
  168. setrl.rlim_max = setrl.rlim_cur;
  169. }
  170. if ( setrlimit( RLIMIT_NOFILE, &setrl ) != 0 && curlim < rl.rlim_max ) {
  171. setrl = rl; /* struct copy */
  172. setrl.rlim_cur = setrl.rlim_max;
  173. if ( setrlimit( RLIMIT_NOFILE, &setrl ) != 0 ) {
  174. int oserr = errno;
  175. LDAPDebug( LDAP_DEBUG_ANY, "setrlimit of descriptor "
  176. "limit to %d failed - error %d (%s)\n",
  177. setrl.rlim_cur, oserr,
  178. slapd_system_strerror(oserr));
  179. return;
  180. }
  181. }
  182. (void)getrlimit( RLIMIT_NOFILE, &rl );
  183. LDAPDebug( LDAP_DEBUG_TRACE, "descriptor limit changed from %d to %d\n",
  184. curlim, rl.rlim_cur, 0 );
  185. }
  186. /*
  187. * Try to raise relevant per-process limits
  188. */
  189. void
  190. raise_process_limits()
  191. {
  192. struct rlimit rl;
  193. raise_process_fd_limits();
  194. #ifdef RLIMIT_DATA
  195. if (getrlimit(RLIMIT_DATA,&rl) == 0) {
  196. rl.rlim_cur = rl.rlim_max;
  197. if (setrlimit(RLIMIT_DATA,&rl) != 0) {
  198. LDAPDebug(LDAP_DEBUG_TRACE,"setrlimit(RLIMIT_DATA) failed %d\n",
  199. errno,0,0);
  200. }
  201. } else {
  202. LDAPDebug(LDAP_DEBUG_TRACE,"getrlimit(RLIMIT_DATA) failed %d\n",
  203. errno,0,0);
  204. }
  205. #endif
  206. #ifdef RLIMIT_VMEM
  207. if (getrlimit(RLIMIT_VMEM,&rl) == 0) {
  208. rl.rlim_cur = rl.rlim_max;
  209. if (setrlimit(RLIMIT_VMEM,&rl) != 0) {
  210. LDAPDebug(LDAP_DEBUG_TRACE,"setrlimit(RLIMIT_VMEM) failed %d\n",
  211. errno,0,0);
  212. }
  213. } else {
  214. LDAPDebug(LDAP_DEBUG_TRACE,"getrlimit(RLIMIT_VMEM) failed %d\n",
  215. errno,0,0);
  216. }
  217. #endif /* RLIMIT_VMEM */
  218. }