1 /*
2    Unix SMB/CIFS implementation.
3 
4    thread model: standard (1 thread per client connection)
5 
6    Copyright (C) Andrew Tridgell 2003-2005
7    Copyright (C) James J Myers 2003 <myersjj@samba.org>
8    Copyright (C) Stefan (metze) Metzmacher 2004
9 
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.
14 
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.
19 
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.
23 */
24 
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 "lib/util/dlinklist.h"
35 #include "lib/util/mutex.h"
36 #include "smbd/process_model.h"
37 
38 static pthread_key_t title_key;
39 
40 struct new_conn_state {
41 	struct event_context *ev;
42 	struct socket_context *sock;
43 	void (*new_conn)(struct event_context *, struct socket_context *, uint32_t , void *);
44 	void *private;
45 };
46 
thread_connection_fn(void * thread_parm)47 static void *thread_connection_fn(void *thread_parm)
48 {
49 	struct new_conn_state *new_conn = talloc_get_type(thread_parm, struct new_conn_state);
50 
51 	new_conn->new_conn(new_conn->ev, new_conn->sock, pthread_self(), new_conn->private);
52 
53 	/* run this connection from here */
54 	event_loop_wait(new_conn->ev);
55 
56 	talloc_free(new_conn);
57 
58 	return NULL;
59 }
60 
61 /*
62   called when a listening socket becomes readable
63 */
thread_accept_connection(struct event_context * ev,struct socket_context * sock,void (* new_conn)(struct event_context *,struct socket_context *,uint32_t,void *),void * private)64 static void thread_accept_connection(struct event_context *ev,
65 				     struct socket_context *sock,
66 				     void (*new_conn)(struct event_context *, struct socket_context *,
67 						      uint32_t , void *),
68 				     void *private)
69 {
70 	NTSTATUS status;
71 	int rc;
72 	pthread_t thread_id;
73 	pthread_attr_t thread_attr;
74 	struct new_conn_state *state;
75 	struct event_context *ev2;
76 
77 	ev2 = event_context_init(ev);
78 	if (ev2 == NULL) return;
79 
80 	state = talloc(ev2, struct new_conn_state);
81 	if (state == NULL) {
82 		talloc_free(ev2);
83 		return;
84 	}
85 
86 	state->new_conn = new_conn;
87 	state->private  = private;
88 	state->ev       = ev2;
89 
90 	/* accept an incoming connection. */
91 	status = socket_accept(sock, &state->sock);
92 	if (!NT_STATUS_IS_OK(status)) {
93 		talloc_free(ev2);
94 		/* We need to throttle things until the system clears
95 		   enough resources to handle this new socket. If we
96 		   don't then we will spin filling the log and causing
97 		   more problems. We don't panic as this is probably a
98 		   temporary resource constraint */
99 		sleep(1);
100 		return;
101 	}
102 
103 	talloc_steal(state, state->sock);
104 
105 	pthread_attr_init(&thread_attr);
106 	pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
107 	rc = pthread_create(&thread_id, &thread_attr, thread_connection_fn, state);
108 	pthread_attr_destroy(&thread_attr);
109 	if (rc == 0) {
110 		DEBUG(4,("accept_connection_thread: created thread_id=%lu for fd=%d\n",
111 			(unsigned long int)thread_id, socket_get_fd(sock)));
112 	} else {
113 		DEBUG(0,("accept_connection_thread: thread create failed for fd=%d, rc=%d\n", socket_get_fd(sock), rc));
114 		talloc_free(ev2);
115 	}
116 }
117 
118 
119 struct new_task_state {
120 	struct event_context *ev;
121 	void (*new_task)(struct event_context *, uint32_t , void *);
122 	void *private;
123 };
124 
thread_task_fn(void * thread_parm)125 static void *thread_task_fn(void *thread_parm)
126 {
127 	struct new_task_state *new_task = talloc_get_type(thread_parm, struct new_task_state);
128 
129 	new_task->new_task(new_task->ev, pthread_self(), new_task->private);
130 
131 	/* run this connection from here */
132 	event_loop_wait(new_task->ev);
133 
134 	talloc_free(new_task);
135 
136 	return NULL;
137 }
138 
139 /*
140   called when a new task is needed
141 */
thread_new_task(struct event_context * ev,void (* new_task)(struct event_context *,uint32_t,void *),void * private)142 static void thread_new_task(struct event_context *ev,
143 			    void (*new_task)(struct event_context *, uint32_t , void *),
144 			    void *private)
145 {
146 	int rc;
147 	pthread_t thread_id;
148 	pthread_attr_t thread_attr;
149 	struct new_task_state *state;
150 	struct event_context *ev2;
151 
152 	ev2 = event_context_init(ev);
153 	if (ev2 == NULL) return;
154 
155 	state = talloc(ev2, struct new_task_state);
156 	if (state == NULL) {
157 		talloc_free(ev2);
158 		return;
159 	}
160 
161 	state->new_task = new_task;
162 	state->private  = private;
163 	state->ev       = ev2;
164 
165 	pthread_attr_init(&thread_attr);
166 	pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
167 	rc = pthread_create(&thread_id, &thread_attr, thread_task_fn, state);
168 	pthread_attr_destroy(&thread_attr);
169 	if (rc == 0) {
170 		DEBUG(4,("thread_new_task: created thread_id=%lu\n",
171 			 (unsigned long int)thread_id));
172 	} else {
173 		DEBUG(0,("thread_new_task: thread create failed rc=%d\n", rc));
174 		talloc_free(ev2);
175 	}
176 }
177 
178 /* called when a task goes down */
thread_terminate(struct event_context * event_ctx,const char * reason)179 static void thread_terminate(struct event_context *event_ctx, const char *reason)
180 {
181 	DEBUG(10,("thread_terminate: reason[%s]\n",reason));
182 
183 	talloc_free(event_ctx);
184 
185 	/* terminate this thread */
186 	pthread_exit(NULL);  /* thread cleanup routine will do actual cleanup */
187 }
188 
189 /* called to set a title of a task or connection */
thread_set_title(struct event_context * ev,const char * title)190 static void thread_set_title(struct event_context *ev, const char *title)
191 {
192 	char *old_title;
193 	char *new_title;
194 
195 	old_title = pthread_getspecific(title_key);
196 	talloc_free(old_title);
197 
198 	new_title = talloc_strdup(ev, title);
199 	pthread_setspecific(title_key, new_title);
200 }
201 
202 /*
203   mutex init function for thread model
204 */
thread_mutex_init(smb_mutex_t * mutex,const char * name)205 static int thread_mutex_init(smb_mutex_t *mutex, const char *name)
206 {
207 	pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
208 	mutex->mutex = memdup(&m, sizeof(m));
209 	if (! mutex->mutex) {
210 		errno = ENOMEM;
211 		return -1;
212 	}
213 	return pthread_mutex_init((pthread_mutex_t *)mutex->mutex, NULL);
214 }
215 
216 /*
217   mutex destroy function for thread model
218 */
thread_mutex_destroy(smb_mutex_t * mutex,const char * name)219 static int thread_mutex_destroy(smb_mutex_t *mutex, const char *name)
220 {
221 	return pthread_mutex_destroy((pthread_mutex_t *)mutex->mutex);
222 }
223 
mutex_start_timer(struct timeval * tp1)224 static void mutex_start_timer(struct timeval *tp1)
225 {
226 	gettimeofday(tp1,NULL);
227 }
228 
mutex_end_timer(struct timeval tp1)229 static double mutex_end_timer(struct timeval tp1)
230 {
231 	struct timeval tp2;
232 	gettimeofday(&tp2,NULL);
233 	return((tp2.tv_sec - tp1.tv_sec) +
234 	       (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
235 }
236 
237 /*
238   mutex lock function for thread model
239 */
thread_mutex_lock(smb_mutex_t * mutexP,const char * name)240 static int thread_mutex_lock(smb_mutex_t *mutexP, const char *name)
241 {
242 	pthread_mutex_t *mutex = (pthread_mutex_t *)mutexP->mutex;
243 	int rc;
244 	double t;
245 	struct timeval tp1;
246 	/* Test below is ONLY for debugging */
247 	if ((rc = pthread_mutex_trylock(mutex))) {
248 		if (rc == EBUSY) {
249 			mutex_start_timer(&tp1);
250 			printf("mutex lock: thread %d, lock %s not available\n",
251 				(uint32_t)pthread_self(), name);
252 			print_suspicious_usage("mutex_lock", name);
253 			pthread_mutex_lock(mutex);
254 			t = mutex_end_timer(tp1);
255 			printf("mutex lock: thread %d, lock %s now available, waited %g seconds\n",
256 				(uint32_t)pthread_self(), name, t);
257 			return 0;
258 		}
259 		printf("mutex lock: thread %d, lock %s failed rc=%d\n",
260 				(uint32_t)pthread_self(), name, rc);
261 		SMB_ASSERT(errno == 0); /* force error */
262 	}
263 	return 0;
264 }
265 
266 /*
267    mutex unlock for thread model
268 */
thread_mutex_unlock(smb_mutex_t * mutex,const char * name)269 static int thread_mutex_unlock(smb_mutex_t *mutex, const char *name)
270 {
271 	return pthread_mutex_unlock((pthread_mutex_t *)mutex->mutex);
272 }
273 
274 /*****************************************************************
275  Read/write lock routines.
276 *****************************************************************/
277 /*
278   rwlock init function for thread model
279 */
thread_rwlock_init(smb_rwlock_t * rwlock,const char * name)280 static int thread_rwlock_init(smb_rwlock_t *rwlock, const char *name)
281 {
282 	pthread_rwlock_t m = PTHREAD_RWLOCK_INITIALIZER;
283 	rwlock->rwlock = memdup(&m, sizeof(m));
284 	if (! rwlock->rwlock) {
285 		errno = ENOMEM;
286 		return -1;
287 	}
288 	return pthread_rwlock_init((pthread_rwlock_t *)rwlock->rwlock, NULL);
289 }
290 
291 /*
292   rwlock destroy function for thread model
293 */
thread_rwlock_destroy(smb_rwlock_t * rwlock,const char * name)294 static int thread_rwlock_destroy(smb_rwlock_t *rwlock, const char *name)
295 {
296 	return pthread_rwlock_destroy((pthread_rwlock_t *)rwlock->rwlock);
297 }
298 
299 /*
300   rwlock lock for read function for thread model
301 */
thread_rwlock_lock_read(smb_rwlock_t * rwlockP,const char * name)302 static int thread_rwlock_lock_read(smb_rwlock_t *rwlockP, const char *name)
303 {
304 	pthread_rwlock_t *rwlock = (pthread_rwlock_t *)rwlockP->rwlock;
305 	int rc;
306 	double t;
307 	struct timeval tp1;
308 	/* Test below is ONLY for debugging */
309 	if ((rc = pthread_rwlock_tryrdlock(rwlock))) {
310 		if (rc == EBUSY) {
311 			mutex_start_timer(&tp1);
312 			printf("rwlock lock_read: thread %d, lock %s not available\n",
313 				(uint32_t)pthread_self(), name);
314 			print_suspicious_usage("rwlock_lock_read", name);
315 			pthread_rwlock_rdlock(rwlock);
316 			t = mutex_end_timer(tp1);
317 			printf("rwlock lock_read: thread %d, lock %s now available, waited %g seconds\n",
318 				(uint32_t)pthread_self(), name, t);
319 			return 0;
320 		}
321 		printf("rwlock lock_read: thread %d, lock %s failed rc=%d\n",
322 				(uint32_t)pthread_self(), name, rc);
323 		SMB_ASSERT(errno == 0); /* force error */
324 	}
325 	return 0;
326 }
327 
328 /*
329   rwlock lock for write function for thread model
330 */
thread_rwlock_lock_write(smb_rwlock_t * rwlockP,const char * name)331 static int thread_rwlock_lock_write(smb_rwlock_t *rwlockP, const char *name)
332 {
333 	pthread_rwlock_t *rwlock = (pthread_rwlock_t *)rwlockP->rwlock;
334 	int rc;
335 	double t;
336 	struct timeval tp1;
337 	/* Test below is ONLY for debugging */
338 	if ((rc = pthread_rwlock_trywrlock(rwlock))) {
339 		if (rc == EBUSY) {
340 			mutex_start_timer(&tp1);
341 			printf("rwlock lock_write: thread %d, lock %s not available\n",
342 				(uint32_t)pthread_self(), name);
343 			print_suspicious_usage("rwlock_lock_write", name);
344 			pthread_rwlock_wrlock(rwlock);
345 			t = mutex_end_timer(tp1);
346 			printf("rwlock lock_write: thread %d, lock %s now available, waited %g seconds\n",
347 				(uint32_t)pthread_self(), name, t);
348 			return 0;
349 		}
350 		printf("rwlock lock_write: thread %d, lock %s failed rc=%d\n",
351 				(uint32_t)pthread_self(), name, rc);
352 		SMB_ASSERT(errno == 0); /* force error */
353 	}
354 	return 0;
355 }
356 
357 
358 /*
359    rwlock unlock for thread model
360 */
thread_rwlock_unlock(smb_rwlock_t * rwlock,const char * name)361 static int thread_rwlock_unlock(smb_rwlock_t *rwlock, const char *name)
362 {
363 	return pthread_rwlock_unlock((pthread_rwlock_t *)rwlock->rwlock);
364 }
365 
366 /*****************************************************************
367  Log suspicious usage (primarily for possible thread-unsafe behavior).
368 *****************************************************************/
thread_log_suspicious_usage(const char * from,const char * info)369 static void thread_log_suspicious_usage(const char* from, const char* info)
370 {
371 	DEBUG(1,("log_suspicious_usage: from %s info='%s'\n", from, info));
372 #ifdef HAVE_BACKTRACE
373 	{
374 		void *addresses[10];
375 		int num_addresses = backtrace(addresses, 8);
376 		char **bt_symbols = backtrace_symbols(addresses, num_addresses);
377 		int i;
378 
379 		if (bt_symbols) {
380 			for (i=0; i<num_addresses; i++) {
381 				DEBUG(1,("log_suspicious_usage: %s%s\n", DEBUGTAB(1), bt_symbols[i]));
382 			}
383 			free(bt_symbols);
384 		}
385 	}
386 #endif
387 }
388 
389 /*****************************************************************
390  Log suspicious usage to stdout (primarily for possible thread-unsafe behavior.
391  Used in mutex code where DEBUG calls would cause recursion.
392 *****************************************************************/
thread_print_suspicious_usage(const char * from,const char * info)393 static void thread_print_suspicious_usage(const char* from, const char* info)
394 {
395 	printf("log_suspicious_usage: from %s info='%s'\n", from, info);
396 #ifdef HAVE_BACKTRACE
397 	{
398 		void *addresses[10];
399 		int num_addresses = backtrace(addresses, 8);
400 		char **bt_symbols = backtrace_symbols(addresses, num_addresses);
401 		int i;
402 
403 		if (bt_symbols) {
404 			for (i=0; i<num_addresses; i++) {
405 				printf("log_suspicious_usage: %s%s\n", DEBUGTAB(1), bt_symbols[i]);
406 			}
407 			free(bt_symbols);
408 		}
409 	}
410 #endif
411 }
412 
thread_get_task_id(void)413 static uint32_t thread_get_task_id(void)
414 {
415 	return (uint32_t)pthread_self();
416 }
417 
thread_log_task_id(int fd)418 static void thread_log_task_id(int fd)
419 {
420 	char *s= NULL;
421 
422 	asprintf(&s, "thread[%u][%s]:\n",
423 		(uint32_t)pthread_self(),
424 		(const char *)pthread_getspecific(title_key));
425 	if (!s) return;
426 	write(fd, s, strlen(s));
427 	free(s);
428 }
429 
430 /****************************************************************************
431 catch serious errors
432 ****************************************************************************/
thread_sig_fault(int sig)433 static void thread_sig_fault(int sig)
434 {
435 	DEBUG(0,("===============================================================\n"));
436 	DEBUG(0,("TERMINAL ERROR: Recursive signal %d in thread [%u][%s] (%s)\n",
437 		sig,(uint32_t)pthread_self(),
438 		(const char *)pthread_getspecific(title_key),
439 		SAMBA_VERSION_STRING));
440 	DEBUG(0,("===============================================================\n"));
441 	exit(1); /* kill the whole server for now */
442 }
443 
444 /*******************************************************************
445 setup our recursive fault handlers
446 ********************************************************************/
thread_fault_setup(void)447 static void thread_fault_setup(void)
448 {
449 #ifdef SIGSEGV
450 	CatchSignal(SIGSEGV,SIGNAL_CAST thread_sig_fault);
451 #endif
452 #ifdef SIGBUS
453 	CatchSignal(SIGBUS,SIGNAL_CAST thread_sig_fault);
454 #endif
455 #ifdef SIGABRT
456 	CatchSignal(SIGABRT,SIGNAL_CAST thread_sig_fault);
457 #endif
458 }
459 
460 /*******************************************************************
461 report a fault in a thread
462 ********************************************************************/
thread_fault_handler(int sig)463 static void thread_fault_handler(int sig)
464 {
465 	static int counter;
466 
467 	/* try to catch recursive faults */
468 	thread_fault_setup();
469 
470 	counter++;	/* count number of faults that have occurred */
471 
472 	DEBUG(0,("===============================================================\n"));
473 	DEBUG(0,("INTERNAL ERROR: Signal %d in thread [%u] [%s] (%s)\n",
474 		sig,(uint32_t)pthread_self(),
475 		(const char *)pthread_getspecific(title_key),
476 		SAMBA_VERSION_STRING));
477 	DEBUG(0,("Please read the file BUGS.txt in the distribution\n"));
478 	DEBUG(0,("===============================================================\n"));
479 #ifdef HAVE_BACKTRACE
480 	{
481 		void *addresses[10];
482 		int num_addresses = backtrace(addresses, 8);
483 		char **bt_symbols = backtrace_symbols(addresses, num_addresses);
484 		int i;
485 
486 		if (bt_symbols) {
487 			for (i=0; i<num_addresses; i++) {
488 				DEBUG(1,("fault_report: %s%s\n", DEBUGTAB(1), bt_symbols[i]));
489 			}
490 			free(bt_symbols);
491 		}
492 	}
493 #endif
494 	pthread_exit(NULL); /* terminate failing thread only */
495 }
496 
497 /*
498   called when the process model is selected
499 */
thread_model_init(struct event_context * event_context)500 static void thread_model_init(struct event_context *event_context)
501 {
502 	struct mutex_ops m_ops;
503 	struct debug_ops d_ops;
504 
505 	ZERO_STRUCT(m_ops);
506 	ZERO_STRUCT(d_ops);
507 
508 	pthread_key_create(&title_key, NULL);
509 	pthread_setspecific(title_key, talloc_strdup(event_context, ""));
510 
511 	/* register mutex/rwlock handlers */
512 	m_ops.mutex_init = thread_mutex_init;
513 	m_ops.mutex_lock = thread_mutex_lock;
514 	m_ops.mutex_unlock = thread_mutex_unlock;
515 	m_ops.mutex_destroy = thread_mutex_destroy;
516 
517 	m_ops.rwlock_init = thread_rwlock_init;
518 	m_ops.rwlock_lock_write = thread_rwlock_lock_write;
519 	m_ops.rwlock_lock_read = thread_rwlock_lock_read;
520 	m_ops.rwlock_unlock = thread_rwlock_unlock;
521 	m_ops.rwlock_destroy = thread_rwlock_destroy;
522 
523 	register_mutex_handlers("thread", &m_ops);
524 
525 	register_fault_handler("thread", thread_fault_handler);
526 
527 	d_ops.log_suspicious_usage = thread_log_suspicious_usage;
528 	d_ops.print_suspicious_usage = thread_print_suspicious_usage;
529 	d_ops.get_task_id = thread_get_task_id;
530 	d_ops.log_task_id = thread_log_task_id;
531 
532 	register_debug_handlers("thread", &d_ops);
533 }
534 
535 
536 static const struct model_ops thread_ops = {
537 	.name			= "thread",
538 	.model_init		= thread_model_init,
539 	.accept_connection	= thread_accept_connection,
540 	.new_task               = thread_new_task,
541 	.terminate              = thread_terminate,
542 	.set_title		= thread_set_title,
543 };
544 
545 /*
546   initialise the thread process model, registering ourselves with the model subsystem
547  */
process_model_thread_init(void)548 NTSTATUS process_model_thread_init(void)
549 {
550 	NTSTATUS ret;
551 
552 	/* register ourselves with the PROCESS_MODEL subsystem. */
553 	ret = register_process_model(&thread_ops);
554 	if (!NT_STATUS_IS_OK(ret)) {
555 		DEBUG(0,("Failed to register process_model 'thread'!\n"));
556 		return ret;
557 	}
558 
559 	return ret;
560 }
561