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.
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"
38 /* For sepecifiying event context to GSSAPI below */
39 #include "heimdal/lib/gssapi/gssapi_locl.h"
41 struct new_conn_state {
42 struct event_context *ev;
43 struct socket_context *sock;
44 void (*new_conn)(struct event_context *, struct socket_context *, uint32_t , void *);
48 static void *thread_connection_fn(void *thread_parm)
50 struct new_conn_state *new_conn = talloc_get_type(thread_parm, struct new_conn_state);
52 new_conn->new_conn(new_conn->ev, new_conn->sock, pthread_self(), new_conn->private);
54 /* run this connection from here */
55 event_loop_wait(new_conn->ev);
57 talloc_free(new_conn);
63 called when a listening socket becomes readable
65 static void thread_accept_connection(struct event_context *ev,
66 struct socket_context *sock,
67 void (*new_conn)(struct event_context *, struct socket_context *,
74 pthread_attr_t thread_attr;
75 struct new_conn_state *state;
76 struct event_context *ev2;
78 ev2 = event_context_init(ev);
79 if (ev2 == NULL) return;
81 state = talloc(ev2, struct new_conn_state);
87 state->new_conn = new_conn;
88 state->private = private;
91 /* accept an incoming connection. */
92 status = socket_accept(sock, &state->sock);
93 if (!NT_STATUS_IS_OK(status)) {
95 /* We need to throttle things until the system clears
96 enough resources to handle this new socket. If we
97 don't then we will spin filling the log and causing
98 more problems. We don't panic as this is probably a
99 temporary resource constraint */
104 talloc_steal(state, state->sock);
106 pthread_attr_init(&thread_attr);
107 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
108 rc = pthread_create(&thread_id, &thread_attr, thread_connection_fn, state);
109 pthread_attr_destroy(&thread_attr);
111 DEBUG(4,("accept_connection_thread: created thread_id=%lu for fd=%d\n",
112 (unsigned long int)thread_id, socket_get_fd(sock)));
114 DEBUG(0,("accept_connection_thread: thread create failed for fd=%d, rc=%d\n", socket_get_fd(sock), rc));
120 struct new_task_state {
121 struct event_context *ev;
122 void (*new_task)(struct event_context *, uint32_t , void *);
126 static void *thread_task_fn(void *thread_parm)
128 struct new_task_state *new_task = talloc_get_type(thread_parm, struct new_task_state);
130 new_task->new_task(new_task->ev, pthread_self(), new_task->private);
132 /* run this connection from here */
133 event_loop_wait(new_task->ev);
135 talloc_free(new_task);
141 called when a new task is needed
143 static void thread_new_task(struct event_context *ev,
144 void (*new_task)(struct event_context *, uint32_t , void *),
149 pthread_attr_t thread_attr;
150 struct new_task_state *state;
151 struct event_context *ev2;
153 ev2 = event_context_init(ev);
154 if (ev2 == NULL) return;
156 state = talloc(ev2, struct new_task_state);
162 state->new_task = new_task;
163 state->private = private;
166 pthread_attr_init(&thread_attr);
167 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
168 rc = pthread_create(&thread_id, &thread_attr, thread_task_fn, state);
169 pthread_attr_destroy(&thread_attr);
171 DEBUG(4,("thread_new_task: created thread_id=%lu\n",
172 (unsigned long int)thread_id));
174 DEBUG(0,("thread_new_task: thread create failed rc=%d\n", rc));
179 /* called when a task goes down */
180 static void thread_terminate(struct event_context *event_ctx, const char *reason)
182 DEBUG(10,("thread_terminate: reason[%s]\n",reason));
184 talloc_free(event_ctx);
186 /* terminate this thread */
187 pthread_exit(NULL); /* thread cleanup routine will do actual cleanup */
191 mutex init function for thread model
193 static int thread_mutex_init(smb_mutex_t *mutex, const char *name)
195 pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
196 mutex->mutex = memdup(&m, sizeof(m));
197 if (! mutex->mutex) {
201 return pthread_mutex_init((pthread_mutex_t *)mutex->mutex, NULL);
205 mutex destroy function for thread model
207 static int thread_mutex_destroy(smb_mutex_t *mutex, const char *name)
209 return pthread_mutex_destroy((pthread_mutex_t *)mutex->mutex);
212 static void mutex_start_timer(struct timeval *tp1)
214 gettimeofday(tp1,NULL);
217 static double mutex_end_timer(struct timeval tp1)
220 gettimeofday(&tp2,NULL);
221 return((tp2.tv_sec - tp1.tv_sec) +
222 (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
226 mutex lock function for thread model
228 static int thread_mutex_lock(smb_mutex_t *mutexP, const char *name)
230 pthread_mutex_t *mutex = (pthread_mutex_t *)mutexP->mutex;
234 /* Test below is ONLY for debugging */
235 if ((rc = pthread_mutex_trylock(mutex))) {
237 mutex_start_timer(&tp1);
238 printf("mutex lock: thread %d, lock %s not available\n",
239 (uint32_t)pthread_self(), name);
240 print_suspicious_usage("mutex_lock", name);
241 pthread_mutex_lock(mutex);
242 t = mutex_end_timer(tp1);
243 printf("mutex lock: thread %d, lock %s now available, waited %g seconds\n",
244 (uint32_t)pthread_self(), name, t);
247 printf("mutex lock: thread %d, lock %s failed rc=%d\n",
248 (uint32_t)pthread_self(), name, rc);
249 SMB_ASSERT(errno == 0); /* force error */
255 mutex unlock for thread model
257 static int thread_mutex_unlock(smb_mutex_t *mutex, const char *name)
259 return pthread_mutex_unlock((pthread_mutex_t *)mutex->mutex);
262 /*****************************************************************
263 Read/write lock routines.
264 *****************************************************************/
266 rwlock init function for thread model
268 static int thread_rwlock_init(smb_rwlock_t *rwlock, const char *name)
270 pthread_rwlock_t m = PTHREAD_RWLOCK_INITIALIZER;
271 rwlock->rwlock = memdup(&m, sizeof(m));
272 if (! rwlock->rwlock) {
276 return pthread_rwlock_init((pthread_rwlock_t *)rwlock->rwlock, NULL);
280 rwlock destroy function for thread model
282 static int thread_rwlock_destroy(smb_rwlock_t *rwlock, const char *name)
284 return pthread_rwlock_destroy((pthread_rwlock_t *)rwlock->rwlock);
288 rwlock lock for read function for thread model
290 static int thread_rwlock_lock_read(smb_rwlock_t *rwlockP, const char *name)
292 pthread_rwlock_t *rwlock = (pthread_rwlock_t *)rwlockP->rwlock;
296 /* Test below is ONLY for debugging */
297 if ((rc = pthread_rwlock_tryrdlock(rwlock))) {
299 mutex_start_timer(&tp1);
300 printf("rwlock lock_read: thread %d, lock %s not available\n",
301 (uint32_t)pthread_self(), name);
302 print_suspicious_usage("rwlock_lock_read", name);
303 pthread_rwlock_rdlock(rwlock);
304 t = mutex_end_timer(tp1);
305 printf("rwlock lock_read: thread %d, lock %s now available, waited %g seconds\n",
306 (uint32_t)pthread_self(), name, t);
309 printf("rwlock lock_read: thread %d, lock %s failed rc=%d\n",
310 (uint32_t)pthread_self(), name, rc);
311 SMB_ASSERT(errno == 0); /* force error */
317 rwlock lock for write function for thread model
319 static int thread_rwlock_lock_write(smb_rwlock_t *rwlockP, const char *name)
321 pthread_rwlock_t *rwlock = (pthread_rwlock_t *)rwlockP->rwlock;
325 /* Test below is ONLY for debugging */
326 if ((rc = pthread_rwlock_trywrlock(rwlock))) {
328 mutex_start_timer(&tp1);
329 printf("rwlock lock_write: thread %d, lock %s not available\n",
330 (uint32_t)pthread_self(), name);
331 print_suspicious_usage("rwlock_lock_write", name);
332 pthread_rwlock_wrlock(rwlock);
333 t = mutex_end_timer(tp1);
334 printf("rwlock lock_write: thread %d, lock %s now available, waited %g seconds\n",
335 (uint32_t)pthread_self(), name, t);
338 printf("rwlock lock_write: thread %d, lock %s failed rc=%d\n",
339 (uint32_t)pthread_self(), name, rc);
340 SMB_ASSERT(errno == 0); /* force error */
347 rwlock unlock for thread model
349 static int thread_rwlock_unlock(smb_rwlock_t *rwlock, const char *name)
351 return pthread_rwlock_unlock((pthread_rwlock_t *)rwlock->rwlock);
354 /*****************************************************************
355 Log suspicious usage (primarily for possible thread-unsafe behavior.
356 *****************************************************************/
357 static void thread_log_suspicious_usage(const char* from, const char* info)
359 DEBUG(1,("log_suspicious_usage: from %s info='%s'\n", from, info));
360 #ifdef HAVE_BACKTRACE
363 int num_addresses = backtrace(addresses, 8);
364 char **bt_symbols = backtrace_symbols(addresses, num_addresses);
368 for (i=0; i<num_addresses; i++) {
369 DEBUG(1,("log_suspicious_usage: %s%s\n", DEBUGTAB(1), bt_symbols[i]));
377 /*****************************************************************
378 Log suspicious usage to stdout (primarily for possible thread-unsafe behavior.
379 Used in mutex code where DEBUG calls would cause recursion.
380 *****************************************************************/
381 static void thread_print_suspicious_usage(const char* from, const char* info)
383 printf("log_suspicious_usage: from %s info='%s'\n", from, info);
384 #ifdef HAVE_BACKTRACE
387 int num_addresses = backtrace(addresses, 8);
388 char **bt_symbols = backtrace_symbols(addresses, num_addresses);
392 for (i=0; i<num_addresses; i++) {
393 printf("log_suspicious_usage: %s%s\n", DEBUGTAB(1), bt_symbols[i]);
401 static uint32_t thread_get_task_id(void)
403 return (uint32_t)pthread_self();
406 static void thread_log_task_id(int fd)
410 asprintf(&s, "thread %u: ", (uint32_t)pthread_self());
412 write(fd, s, strlen(s));
416 /****************************************************************************
418 ****************************************************************************/
419 static void thread_sig_fault(int sig)
421 DEBUG(0,("===============================================================\n"));
422 DEBUG(0,("TERMINAL ERROR: Recursive signal %d in thread %lu (%s)\n",sig,(unsigned long int)pthread_self(),SAMBA_VERSION_STRING));
423 DEBUG(0,("===============================================================\n"));
424 exit(1); /* kill the whole server for now */
427 /*******************************************************************
428 setup our recursive fault handlers
429 ********************************************************************/
430 static void thread_fault_setup(void)
433 CatchSignal(SIGSEGV,SIGNAL_CAST thread_sig_fault);
436 CatchSignal(SIGBUS,SIGNAL_CAST thread_sig_fault);
439 CatchSignal(SIGABRT,SIGNAL_CAST thread_sig_fault);
443 /*******************************************************************
444 report a fault in a thread
445 ********************************************************************/
446 static void thread_fault_handler(int sig)
450 /* try to catch recursive faults */
451 thread_fault_setup();
453 counter++; /* count number of faults that have occurred */
455 DEBUG(0,("===============================================================\n"));
456 DEBUG(0,("INTERNAL ERROR: Signal %d in thread %lu (%s)\n",sig,(unsigned long int)pthread_self(),SAMBA_VERSION_STRING));
457 DEBUG(0,("Please read the file BUGS.txt in the distribution\n"));
458 DEBUG(0,("===============================================================\n"));
459 #ifdef HAVE_BACKTRACE
462 int num_addresses = backtrace(addresses, 8);
463 char **bt_symbols = backtrace_symbols(addresses, num_addresses);
467 for (i=0; i<num_addresses; i++) {
468 DEBUG(1,("fault_report: %s%s\n", DEBUGTAB(1), bt_symbols[i]));
474 pthread_exit(NULL); /* terminate failing thread only */
478 called when the process model is selected
480 static void thread_model_init(struct event_context *event_context)
482 struct mutex_ops m_ops;
483 struct debug_ops d_ops;
488 /* register mutex/rwlock handlers */
489 m_ops.mutex_init = thread_mutex_init;
490 m_ops.mutex_lock = thread_mutex_lock;
491 m_ops.mutex_unlock = thread_mutex_unlock;
492 m_ops.mutex_destroy = thread_mutex_destroy;
494 m_ops.rwlock_init = thread_rwlock_init;
495 m_ops.rwlock_lock_write = thread_rwlock_lock_write;
496 m_ops.rwlock_lock_read = thread_rwlock_lock_read;
497 m_ops.rwlock_unlock = thread_rwlock_unlock;
498 m_ops.rwlock_destroy = thread_rwlock_destroy;
500 register_mutex_handlers("thread", &m_ops);
502 register_fault_handler("thread", thread_fault_handler);
504 d_ops.log_suspicious_usage = thread_log_suspicious_usage;
505 d_ops.print_suspicious_usage = thread_print_suspicious_usage;
506 d_ops.get_task_id = thread_get_task_id;
507 d_ops.log_task_id = thread_log_task_id;
509 register_debug_handlers("thread", &d_ops);
511 /* Hack to ensure that GSSAPI uses the right event context */
512 gssapi_krb5_init_ev(event_context);
516 static const struct model_ops thread_ops = {
518 .model_init = thread_model_init,
519 .accept_connection = thread_accept_connection,
520 .new_task = thread_new_task,
521 .terminate = thread_terminate,
525 initialise the thread process model, registering ourselves with the model subsystem
527 NTSTATUS process_model_thread_init(void)
531 /* register ourselves with the PROCESS_MODEL subsystem. */
532 ret = register_process_model(&thread_ops);
533 if (!NT_STATUS_IS_OK(ret)) {
534 DEBUG(0,("Failed to register process_model 'thread'!\n"));