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 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 *);
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
);
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
*,
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
);
84 state
->new_conn
= new_conn
;
85 state
->private = private;
88 /* accept an incoming connection. */
89 status
= socket_accept(sock
, &state
->sock
);
90 if (!NT_STATUS_IS_OK(status
)) {
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
);
102 DEBUG(4,("accept_connection_thread: created thread_id=%lu for fd=%d\n",
103 (unsigned long int)thread_id
, socket_get_fd(sock
)));
105 DEBUG(0,("accept_connection_thread: thread create failed for fd=%d, rc=%d\n", socket_get_fd(sock
), rc
));
111 struct new_task_state
{
112 struct event_context
*ev
;
113 void (*new_task
)(struct event_context
*, uint32_t , void *);
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
);
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 *),
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
);
153 state
->new_task
= new_task
;
154 state
->private = private;
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
);
162 DEBUG(4,("thread_new_task: created thread_id=%lu\n",
163 (unsigned long int)thread_id
));
165 DEBUG(0,("thread_new_task: thread create failed rc=%d\n", rc
));
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
) {
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
)
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
;
225 /* Test below is ONLY for debugging */
226 if ((rc
= pthread_mutex_trylock(mutex
))) {
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
);
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 */
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
) {
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
;
287 /* Test below is ONLY for debugging */
288 if ((rc
= pthread_rwlock_tryrdlock(rwlock
))) {
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
);
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 */
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
;
316 /* Test below is ONLY for debugging */
317 if ((rc
= pthread_rwlock_trywrlock(rwlock
))) {
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
);
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 */
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
354 int num_addresses
= backtrace(addresses
, 8);
355 char **bt_symbols
= backtrace_symbols(addresses
, num_addresses
);
359 for (i
=0; i
<num_addresses
; i
++) {
360 DEBUG(1,("log_suspicious_usage: %s%s\n", DEBUGTAB(1), bt_symbols
[i
]));
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
378 int num_addresses
= backtrace(addresses
, 8);
379 char **bt_symbols
= backtrace_symbols(addresses
, num_addresses
);
383 for (i
=0; i
<num_addresses
; i
++) {
384 printf("log_suspicious_usage: %s%s\n", DEBUGTAB(1), bt_symbols
[i
]);
392 static uint32_t thread_get_task_id(void)
394 return (uint32_t)pthread_self();
397 static void thread_log_task_id(int fd
)
401 asprintf(&s
, "thread %u: ", (uint32_t)pthread_self());
402 write(fd
, s
, strlen(s
));
406 /****************************************************************************
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)
423 CatchSignal(SIGSEGV
,SIGNAL_CAST thread_sig_fault
);
426 CatchSignal(SIGBUS
,SIGNAL_CAST thread_sig_fault
);
429 CatchSignal(SIGABRT
,SIGNAL_CAST thread_sig_fault
);
433 /*******************************************************************
434 report a fault in a thread
435 ********************************************************************/
436 static void thread_fault_handler(int sig
)
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
452 int num_addresses
= backtrace(addresses
, 8);
453 char **bt_symbols
= backtrace_symbols(addresses
, num_addresses
);
457 for (i
=0; i
<num_addresses
; i
++) {
458 DEBUG(1,("fault_report: %s%s\n", DEBUGTAB(1), bt_symbols
[i
]));
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
;
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
= {
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)
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"));