r6226: A couple of small typos ...
[Samba/gebeck_regimport.git] / source4 / smbd / process_thread.c
blob692cd067240de802f005bf71a1280f82bcf5df09
1 /*
2 Unix SMB/CIFS implementation.
4 thread model: standard (1 thread per client connection)
6 Copyright (C) Andrew Tridgell 2003-2005
7 Copyright (C) James J Myers 2003 <myersjj@samba.org>
8 Copyright (C) Stefan (metze) Metzmacher 2004
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "includes.h"
26 #include "version.h"
27 #include <pthread.h>
28 #ifdef HAVE_BACKTRACE
29 #include <execinfo.h>
30 #endif
31 #include "system/wait.h"
32 #include "system/filesys.h"
33 #include "lib/events/events.h"
34 #include "dlinklist.h"
35 #include "smb_server/smb_server.h"
36 #include "mutex.h"
38 struct new_conn_state {
39 struct event_context *ev;
40 struct socket_context *sock;
41 void (*new_conn)(struct event_context *, struct socket_context *, uint32_t , void *);
42 void *private;
45 static void *thread_connection_fn(void *thread_parm)
47 struct new_conn_state *new_conn = talloc_get_type(thread_parm, struct new_conn_state);
49 new_conn->new_conn(new_conn->ev, new_conn->sock, pthread_self(), new_conn->private);
51 /* run this connection from here */
52 event_loop_wait(new_conn->ev);
54 talloc_free(new_conn);
56 return NULL;
60 called when a listening socket becomes readable
62 static void thread_accept_connection(struct event_context *ev,
63 struct socket_context *sock,
64 void (*new_conn)(struct event_context *, struct socket_context *,
65 uint32_t , void *),
66 void *private)
68 NTSTATUS status;
69 int rc;
70 pthread_t thread_id;
71 pthread_attr_t thread_attr;
72 struct new_conn_state *state;
73 struct event_context *ev2;
75 ev2 = event_context_init(ev);
76 if (ev2 == NULL) return;
78 state = talloc(ev2, struct new_conn_state);
79 if (state == NULL) {
80 talloc_free(ev2);
81 return;
84 state->new_conn = new_conn;
85 state->private = private;
86 state->ev = ev2;
88 /* accept an incoming connection. */
89 status = socket_accept(sock, &state->sock);
90 if (!NT_STATUS_IS_OK(status)) {
91 talloc_free(ev2);
92 return;
95 talloc_steal(state, state->sock);
97 pthread_attr_init(&thread_attr);
98 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
99 rc = pthread_create(&thread_id, &thread_attr, thread_connection_fn, state);
100 pthread_attr_destroy(&thread_attr);
101 if (rc == 0) {
102 DEBUG(4,("accept_connection_thread: created thread_id=%lu for fd=%d\n",
103 (unsigned long int)thread_id, socket_get_fd(sock)));
104 } else {
105 DEBUG(0,("accept_connection_thread: thread create failed for fd=%d, rc=%d\n", socket_get_fd(sock), rc));
106 talloc_free(ev2);
111 struct new_task_state {
112 struct event_context *ev;
113 void (*new_task)(struct event_context *, uint32_t , void *);
114 void *private;
117 static void *thread_task_fn(void *thread_parm)
119 struct new_task_state *new_task = talloc_get_type(thread_parm, struct new_task_state);
121 new_task->new_task(new_task->ev, pthread_self(), new_task->private);
123 /* run this connection from here */
124 event_loop_wait(new_task->ev);
126 talloc_free(new_task);
128 return NULL;
132 called when a new task is needed
134 static void thread_new_task(struct event_context *ev,
135 void (*new_task)(struct event_context *, uint32_t , void *),
136 void *private)
138 int rc;
139 pthread_t thread_id;
140 pthread_attr_t thread_attr;
141 struct new_task_state *state;
142 struct event_context *ev2;
144 ev2 = event_context_init(ev);
145 if (ev2 == NULL) return;
147 state = talloc(ev2, struct new_task_state);
148 if (state == NULL) {
149 talloc_free(ev2);
150 return;
153 state->new_task = new_task;
154 state->private = private;
155 state->ev = ev2;
157 pthread_attr_init(&thread_attr);
158 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
159 rc = pthread_create(&thread_id, &thread_attr, thread_task_fn, state);
160 pthread_attr_destroy(&thread_attr);
161 if (rc == 0) {
162 DEBUG(4,("thread_new_task: created thread_id=%lu\n",
163 (unsigned long int)thread_id));
164 } else {
165 DEBUG(0,("thread_new_task: thread create failed rc=%d\n", rc));
166 talloc_free(ev2);
170 /* called when a task goes down */
171 static void thread_terminate(struct event_context *event_ctx, const char *reason)
173 DEBUG(10,("thread_terminate: reason[%s]\n",reason));
175 talloc_free(event_ctx);
177 /* terminate this thread */
178 pthread_exit(NULL); /* thread cleanup routine will do actual cleanup */
182 mutex init function for thread model
184 static int thread_mutex_init(smb_mutex_t *mutex, const char *name)
186 pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
187 mutex->mutex = memdup(&m, sizeof(m));
188 if (! mutex->mutex) {
189 errno = ENOMEM;
190 return -1;
192 return pthread_mutex_init((pthread_mutex_t *)mutex->mutex, NULL);
196 mutex destroy function for thread model
198 static int thread_mutex_destroy(smb_mutex_t *mutex, const char *name)
200 return pthread_mutex_destroy((pthread_mutex_t *)mutex->mutex);
203 static void mutex_start_timer(struct timeval *tp1)
205 gettimeofday(tp1,NULL);
208 static double mutex_end_timer(struct timeval tp1)
210 struct timeval tp2;
211 gettimeofday(&tp2,NULL);
212 return((tp2.tv_sec - tp1.tv_sec) +
213 (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
217 mutex lock function for thread model
219 static int thread_mutex_lock(smb_mutex_t *mutexP, const char *name)
221 pthread_mutex_t *mutex = (pthread_mutex_t *)mutexP->mutex;
222 int rc;
223 double t;
224 struct timeval tp1;
225 /* Test below is ONLY for debugging */
226 if ((rc = pthread_mutex_trylock(mutex))) {
227 if (rc == EBUSY) {
228 mutex_start_timer(&tp1);
229 printf("mutex lock: thread %d, lock %s not available\n",
230 (uint32_t)pthread_self(), name);
231 print_suspicious_usage("mutex_lock", name);
232 pthread_mutex_lock(mutex);
233 t = mutex_end_timer(tp1);
234 printf("mutex lock: thread %d, lock %s now available, waited %g seconds\n",
235 (uint32_t)pthread_self(), name, t);
236 return 0;
238 printf("mutex lock: thread %d, lock %s failed rc=%d\n",
239 (uint32_t)pthread_self(), name, rc);
240 SMB_ASSERT(errno == 0); /* force error */
242 return 0;
246 mutex unlock for thread model
248 static int thread_mutex_unlock(smb_mutex_t *mutex, const char *name)
250 return pthread_mutex_unlock((pthread_mutex_t *)mutex->mutex);
253 /*****************************************************************
254 Read/write lock routines.
255 *****************************************************************/
257 rwlock init function for thread model
259 static int thread_rwlock_init(smb_rwlock_t *rwlock, const char *name)
261 pthread_rwlock_t m = PTHREAD_RWLOCK_INITIALIZER;
262 rwlock->rwlock = memdup(&m, sizeof(m));
263 if (! rwlock->rwlock) {
264 errno = ENOMEM;
265 return -1;
267 return pthread_rwlock_init((pthread_rwlock_t *)rwlock->rwlock, NULL);
271 rwlock destroy function for thread model
273 static int thread_rwlock_destroy(smb_rwlock_t *rwlock, const char *name)
275 return pthread_rwlock_destroy((pthread_rwlock_t *)rwlock->rwlock);
279 rwlock lock for read function for thread model
281 static int thread_rwlock_lock_read(smb_rwlock_t *rwlockP, const char *name)
283 pthread_rwlock_t *rwlock = (pthread_rwlock_t *)rwlockP->rwlock;
284 int rc;
285 double t;
286 struct timeval tp1;
287 /* Test below is ONLY for debugging */
288 if ((rc = pthread_rwlock_tryrdlock(rwlock))) {
289 if (rc == EBUSY) {
290 mutex_start_timer(&tp1);
291 printf("rwlock lock_read: thread %d, lock %s not available\n",
292 (uint32_t)pthread_self(), name);
293 print_suspicious_usage("rwlock_lock_read", name);
294 pthread_rwlock_rdlock(rwlock);
295 t = mutex_end_timer(tp1);
296 printf("rwlock lock_read: thread %d, lock %s now available, waited %g seconds\n",
297 (uint32_t)pthread_self(), name, t);
298 return 0;
300 printf("rwlock lock_read: thread %d, lock %s failed rc=%d\n",
301 (uint32_t)pthread_self(), name, rc);
302 SMB_ASSERT(errno == 0); /* force error */
304 return 0;
308 rwlock lock for write function for thread model
310 static int thread_rwlock_lock_write(smb_rwlock_t *rwlockP, const char *name)
312 pthread_rwlock_t *rwlock = (pthread_rwlock_t *)rwlockP->rwlock;
313 int rc;
314 double t;
315 struct timeval tp1;
316 /* Test below is ONLY for debugging */
317 if ((rc = pthread_rwlock_trywrlock(rwlock))) {
318 if (rc == EBUSY) {
319 mutex_start_timer(&tp1);
320 printf("rwlock lock_write: thread %d, lock %s not available\n",
321 (uint32_t)pthread_self(), name);
322 print_suspicious_usage("rwlock_lock_write", name);
323 pthread_rwlock_wrlock(rwlock);
324 t = mutex_end_timer(tp1);
325 printf("rwlock lock_write: thread %d, lock %s now available, waited %g seconds\n",
326 (uint32_t)pthread_self(), name, t);
327 return 0;
329 printf("rwlock lock_write: thread %d, lock %s failed rc=%d\n",
330 (uint32_t)pthread_self(), name, rc);
331 SMB_ASSERT(errno == 0); /* force error */
333 return 0;
338 rwlock unlock for thread model
340 static int thread_rwlock_unlock(smb_rwlock_t *rwlock, const char *name)
342 return pthread_rwlock_unlock((pthread_rwlock_t *)rwlock->rwlock);
345 /*****************************************************************
346 Log suspicious usage (primarily for possible thread-unsafe behavior.
347 *****************************************************************/
348 static void thread_log_suspicious_usage(const char* from, const char* info)
350 DEBUG(1,("log_suspicious_usage: from %s info='%s'\n", from, info));
351 #ifdef HAVE_BACKTRACE
353 void *addresses[10];
354 int num_addresses = backtrace(addresses, 8);
355 char **bt_symbols = backtrace_symbols(addresses, num_addresses);
356 int i;
358 if (bt_symbols) {
359 for (i=0; i<num_addresses; i++) {
360 DEBUG(1,("log_suspicious_usage: %s%s\n", DEBUGTAB(1), bt_symbols[i]));
362 free(bt_symbols);
365 #endif
368 /*****************************************************************
369 Log suspicious usage to stdout (primarily for possible thread-unsafe behavior.
370 Used in mutex code where DEBUG calls would cause recursion.
371 *****************************************************************/
372 static void thread_print_suspicious_usage(const char* from, const char* info)
374 printf("log_suspicious_usage: from %s info='%s'\n", from, info);
375 #ifdef HAVE_BACKTRACE
377 void *addresses[10];
378 int num_addresses = backtrace(addresses, 8);
379 char **bt_symbols = backtrace_symbols(addresses, num_addresses);
380 int i;
382 if (bt_symbols) {
383 for (i=0; i<num_addresses; i++) {
384 printf("log_suspicious_usage: %s%s\n", DEBUGTAB(1), bt_symbols[i]);
386 free(bt_symbols);
389 #endif
392 static uint32_t thread_get_task_id(void)
394 return (uint32_t)pthread_self();
397 static void thread_log_task_id(int fd)
399 char *s;
401 asprintf(&s, "thread %u: ", (uint32_t)pthread_self());
402 write(fd, s, strlen(s));
403 free(s);
406 /****************************************************************************
407 catch serious errors
408 ****************************************************************************/
409 static void thread_sig_fault(int sig)
411 DEBUG(0,("===============================================================\n"));
412 DEBUG(0,("TERMINAL ERROR: Recursive signal %d in thread %lu (%s)\n",sig,(unsigned long int)pthread_self(),SAMBA_VERSION_STRING));
413 DEBUG(0,("===============================================================\n"));
414 exit(1); /* kill the whole server for now */
417 /*******************************************************************
418 setup our recursive fault handlers
419 ********************************************************************/
420 static void thread_fault_setup(void)
422 #ifdef SIGSEGV
423 CatchSignal(SIGSEGV,SIGNAL_CAST thread_sig_fault);
424 #endif
425 #ifdef SIGBUS
426 CatchSignal(SIGBUS,SIGNAL_CAST thread_sig_fault);
427 #endif
428 #ifdef SIGABRT
429 CatchSignal(SIGABRT,SIGNAL_CAST thread_sig_fault);
430 #endif
433 /*******************************************************************
434 report a fault in a thread
435 ********************************************************************/
436 static void thread_fault_handler(int sig)
438 static int counter;
440 /* try to catch recursive faults */
441 thread_fault_setup();
443 counter++; /* count number of faults that have occurred */
445 DEBUG(0,("===============================================================\n"));
446 DEBUG(0,("INTERNAL ERROR: Signal %d in thread %lu (%s)\n",sig,(unsigned long int)pthread_self(),SAMBA_VERSION_STRING));
447 DEBUG(0,("Please read the file BUGS.txt in the distribution\n"));
448 DEBUG(0,("===============================================================\n"));
449 #ifdef HAVE_BACKTRACE
451 void *addresses[10];
452 int num_addresses = backtrace(addresses, 8);
453 char **bt_symbols = backtrace_symbols(addresses, num_addresses);
454 int i;
456 if (bt_symbols) {
457 for (i=0; i<num_addresses; i++) {
458 DEBUG(1,("fault_report: %s%s\n", DEBUGTAB(1), bt_symbols[i]));
460 free(bt_symbols);
463 #endif
464 pthread_exit(NULL); /* terminate failing thread only */
468 called when the process model is selected
470 static void thread_model_init(struct event_context *event_context)
472 struct mutex_ops m_ops;
473 struct debug_ops d_ops;
475 ZERO_STRUCT(m_ops);
476 ZERO_STRUCT(d_ops);
478 /* register mutex/rwlock handlers */
479 m_ops.mutex_init = thread_mutex_init;
480 m_ops.mutex_lock = thread_mutex_lock;
481 m_ops.mutex_unlock = thread_mutex_unlock;
482 m_ops.mutex_destroy = thread_mutex_destroy;
484 m_ops.rwlock_init = thread_rwlock_init;
485 m_ops.rwlock_lock_write = thread_rwlock_lock_write;
486 m_ops.rwlock_lock_read = thread_rwlock_lock_read;
487 m_ops.rwlock_unlock = thread_rwlock_unlock;
488 m_ops.rwlock_destroy = thread_rwlock_destroy;
490 register_mutex_handlers("thread", &m_ops);
492 register_fault_handler("thread", thread_fault_handler);
494 d_ops.log_suspicious_usage = thread_log_suspicious_usage;
495 d_ops.print_suspicious_usage = thread_print_suspicious_usage;
496 d_ops.get_task_id = thread_get_task_id;
497 d_ops.log_task_id = thread_log_task_id;
499 register_debug_handlers("thread", &d_ops);
503 static const struct model_ops thread_ops = {
504 .name = "thread",
505 .model_init = thread_model_init,
506 .accept_connection = thread_accept_connection,
507 .new_task = thread_new_task,
508 .terminate = thread_terminate,
512 initialise the thread process model, registering ourselves with the model subsystem
514 NTSTATUS process_model_thread_init(void)
516 NTSTATUS ret;
518 /* register ourselves with the PROCESS_MODEL subsystem. */
519 ret = register_process_model(&thread_ops);
520 if (!NT_STATUS_IS_OK(ret)) {
521 DEBUG(0,("Failed to register process_model 'thread'!\n"));
522 return ret;
525 return ret;