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