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