detach.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. /*
  39. * Copyright (c) 1990, 1994 Regents of the University of Michigan.
  40. * All rights reserved.
  41. *
  42. * Redistribution and use in source and binary forms are permitted
  43. * provided that this notice is preserved and that due credit is given
  44. * to the University of Michigan at Ann Arbor. The name of the University
  45. * may not be used to endorse or promote products derived from this
  46. * software without specific prior written permission. This software
  47. * is provided ``as is'' without express or implied warranty.
  48. */
  49. #include <stdio.h>
  50. #include <sys/types.h>
  51. #ifdef SVR4
  52. #include <sys/stat.h>
  53. #endif /* svr4 */
  54. #include <fcntl.h>
  55. #ifndef _WIN32
  56. #include <errno.h>
  57. #include <sys/file.h>
  58. #include <sys/ioctl.h>
  59. #include <sys/resource.h>
  60. #endif
  61. #include <signal.h>
  62. #ifdef LINUX
  63. #undef CTIME
  64. #endif
  65. #include "slap.h"
  66. #include "fe.h"
  67. #if defined(USE_SYSCONF) || defined(LINUX)
  68. #include <unistd.h>
  69. #endif /* USE_SYSCONF */
  70. void
  71. detach()
  72. {
  73. #ifndef _WIN32
  74. int i, sd;
  75. char *workingdir = 0;
  76. char *errorlog = 0;
  77. char *ptr = 0;
  78. char errorbuf[BUFSIZ];
  79. extern char *config_get_errorlog(void);
  80. #endif
  81. #ifndef _WIN32
  82. if ( should_detach ) {
  83. for ( i = 0; i < 5; i++ ) {
  84. #if defined( sunos5 ) && ( defined( THREAD_SUNOS5_LWP ) || defined( NSPR20 ))
  85. switch ( fork1() ) {
  86. #else
  87. switch ( fork() ) {
  88. #endif
  89. case -1:
  90. sleep( 5 );
  91. continue;
  92. case 0:
  93. break;
  94. default:
  95. _exit( 0 );
  96. }
  97. break;
  98. }
  99. workingdir = config_get_workingdir();
  100. if ( NULL == workingdir ) {
  101. errorlog = config_get_errorlog();
  102. if ( NULL == errorlog ) {
  103. (void) chdir( "/" );
  104. } else {
  105. if ((ptr = strrchr(errorlog, '/')) ||
  106. (ptr = strrchr(errorlog, '\\'))) {
  107. *ptr = 0;
  108. }
  109. (void) chdir( errorlog );
  110. config_set_workingdir(CONFIG_WORKINGDIR_ATTRIBUTE, errorlog, errorbuf, 1);
  111. slapi_ch_free((void**)&errorlog);
  112. }
  113. } else {
  114. /* calling config_set_workingdir to check for validity of directory, don't apply */
  115. if (config_set_workingdir(CONFIG_WORKINGDIR_ATTRIBUTE, workingdir, errorbuf, 0) == LDAP_OPERATIONS_ERROR) {
  116. exit(1);
  117. }
  118. (void) chdir( workingdir );
  119. slapi_ch_free((void**)&workingdir);
  120. }
  121. if ( (sd = open( "/dev/null", O_RDWR )) == -1 ) {
  122. perror( "/dev/null" );
  123. exit( 1 );
  124. }
  125. (void) dup2( sd, 0 );
  126. (void) dup2( sd, 1 );
  127. (void) dup2( sd, 2 );
  128. close( sd );
  129. #ifdef USE_SETSID
  130. setsid();
  131. #else /* USE_SETSID */
  132. if ( (sd = open( "/dev/tty", O_RDWR )) != -1 ) {
  133. (void) ioctl( sd, TIOCNOTTY, NULL );
  134. (void) close( sd );
  135. }
  136. #endif /* USE_SETSID */
  137. g_set_detached(1);
  138. }
  139. (void) SIGNAL( SIGPIPE, SIG_IGN );
  140. #endif /* _WIN32 */
  141. }
  142. #ifndef _WIN32
  143. /*
  144. * close all open files except stdin/out/err
  145. */
  146. void
  147. close_all_files()
  148. {
  149. int i, nbits;
  150. #ifdef USE_SYSCONF
  151. nbits = sysconf( _SC_OPEN_MAX );
  152. #else /* USE_SYSCONF */
  153. nbits = getdtablesize();
  154. #endif /* USE_SYSCONF */
  155. for ( i = 3; i < nbits; i++ ) {
  156. close( i );
  157. }
  158. }
  159. #endif /* !_WIN32 */
  160. /*
  161. * There is no need to do anything on some platforms (NT) and not try to
  162. * raise fds on AIX.
  163. */
  164. static void raise_process_fd_limits(void)
  165. {
  166. #if !defined(_WIN32) && !defined(AIX)
  167. struct rlimit rl, setrl;
  168. RLIM_TYPE curlim;
  169. slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
  170. if ( slapdFrontendConfig->maxdescriptors < 0 ) {
  171. return;
  172. }
  173. /*
  174. * Try to set our file descriptor limit. Our basic strategy is:
  175. * 1) Try to set the soft limit and the hard limit if
  176. * necessary to match our maxdescriptors value.
  177. * 2) If that fails and our soft limit is less than our hard
  178. * limit, we try to raise it to match the hard.
  179. */
  180. if ( getrlimit( RLIMIT_NOFILE, &rl ) != 0 ) {
  181. int oserr = errno;
  182. LDAPDebug( LDAP_DEBUG_ANY,
  183. "getrlimit of descriptor limit failed - error %d (%s)\n",
  184. oserr, slapd_system_strerror( oserr ), 0 );
  185. return;
  186. }
  187. if ( rl.rlim_cur == slapdFrontendConfig->maxdescriptors ) { /* already correct */
  188. return;
  189. }
  190. curlim = rl.rlim_cur;
  191. setrl = rl; /* struct copy */
  192. setrl.rlim_cur = slapdFrontendConfig->maxdescriptors;
  193. /* don't lower the hard limit as it's irreversible */
  194. if (setrl.rlim_cur > setrl.rlim_max) {
  195. setrl.rlim_max = setrl.rlim_cur;
  196. }
  197. if ( setrlimit( RLIMIT_NOFILE, &setrl ) != 0 && curlim < rl.rlim_max ) {
  198. setrl = rl; /* struct copy */
  199. setrl.rlim_cur = setrl.rlim_max;
  200. if ( setrlimit( RLIMIT_NOFILE, &setrl ) != 0 ) {
  201. int oserr = errno;
  202. LDAPDebug( LDAP_DEBUG_ANY, "setrlimit of descriptor "
  203. "limit to %d failed - error %d (%s)\n",
  204. setrl.rlim_cur, oserr,
  205. slapd_system_strerror(oserr));
  206. return;
  207. }
  208. }
  209. (void)getrlimit( RLIMIT_NOFILE, &rl );
  210. LDAPDebug( LDAP_DEBUG_TRACE, "descriptor limit changed from %d to %d\n",
  211. curlim, rl.rlim_cur, 0 );
  212. #endif /* !_WIN32 && !AIX */
  213. }
  214. /*
  215. * Try to raise relevant per-process limits
  216. */
  217. void
  218. raise_process_limits()
  219. {
  220. #if !defined(_WIN32)
  221. struct rlimit rl;
  222. raise_process_fd_limits();
  223. #ifdef RLIMIT_DATA
  224. if (getrlimit(RLIMIT_DATA,&rl) == 0) {
  225. rl.rlim_cur = rl.rlim_max;
  226. if (setrlimit(RLIMIT_DATA,&rl) != 0) {
  227. LDAPDebug(LDAP_DEBUG_TRACE,"setrlimit(RLIMIT_DATA) failed %d\n",
  228. errno,0,0);
  229. }
  230. } else {
  231. LDAPDebug(LDAP_DEBUG_TRACE,"getrlimit(RLIMIT_DATA) failed %d\n",
  232. errno,0,0);
  233. }
  234. #endif
  235. #ifdef RLIMIT_VMEM
  236. if (getrlimit(RLIMIT_VMEM,&rl) == 0) {
  237. rl.rlim_cur = rl.rlim_max;
  238. if (setrlimit(RLIMIT_VMEM,&rl) != 0) {
  239. LDAPDebug(LDAP_DEBUG_TRACE,"setrlimit(RLIMIT_VMEM) failed %d\n",
  240. errno,0,0);
  241. }
  242. } else {
  243. LDAPDebug(LDAP_DEBUG_TRACE,"getrlimit(RLIMIT_VMEM) failed %d\n",
  244. errno,0,0);
  245. }
  246. #endif /* RLIMIT_VMEM */
  247. #endif /* !_WIN32 */
  248. }