annotate src/misc/ngx_google_perftools_module.c @ 3293:8abb88374c6c

Fix a bug introduced in r2032: After a child process has read a terminate message from a channel, the process tries to read the channel again. The kernel (at least FreeBSD) may preempt the process and sends a SIGIO signal to a master process. The master process sends a new terminate message, the kernel switches again to the the child process, and the child process reads the messages instead of an EAGAIN error. And this may repeat over and over. Being that the child process can not exit the cycle and test the termination flag set by the message handler. The fix disallow the master process to send a new terminate message on SIGIO signal reception. It may send the message only on SIGALARM signal.
author Igor Sysoev <igor@sysoev.ru>
date Wed, 04 Nov 2009 19:41:08 +0000
parents e5ce4e2de846
children eb8660fecc12
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1949
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
1
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
2 /*
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
3 * Copyright (C) Igor Sysoev
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
4 */
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
5
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
6
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
7 #include <ngx_config.h>
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
8 #include <ngx_core.h>
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
9
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
10 /*
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
11 * declare Profiler here interface because
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
12 * <google/profiler.h> is C++ header file
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
13 */
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
14
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
15 int ProfilerStart(u_char* fname);
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
16 void ProfilerStop(void);
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
17 void ProfilerRegisterThread(void);
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
18
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
19
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
20 static void *ngx_google_perftools_create_conf(ngx_cycle_t *cycle);
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
21 static ngx_int_t ngx_google_perftools_worker(ngx_cycle_t *cycle);
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
22
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
23
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
24 typedef struct {
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
25 ngx_str_t profiles;
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
26 } ngx_google_perftools_conf_t;
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
27
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
28
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
29 static ngx_command_t ngx_google_perftools_commands[] = {
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
30
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
31 { ngx_string("google_perftools_profiles"),
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
32 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
33 ngx_conf_set_str_slot,
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
34 0,
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
35 offsetof(ngx_google_perftools_conf_t, profiles),
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
36 NULL },
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
37
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
38 ngx_null_command
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
39 };
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
40
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
41
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
42 static ngx_core_module_t ngx_google_perftools_module_ctx = {
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
43 ngx_string("google_perftools"),
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
44 ngx_google_perftools_create_conf,
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
45 NULL
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
46 };
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
47
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
48
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
49 ngx_module_t ngx_google_perftools_module = {
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
50 NGX_MODULE_V1,
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
51 &ngx_google_perftools_module_ctx, /* module context */
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
52 ngx_google_perftools_commands, /* module directives */
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
53 NGX_CORE_MODULE, /* module type */
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
54 NULL, /* init master */
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
55 NULL, /* init module */
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
56 ngx_google_perftools_worker, /* init process */
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
57 NULL, /* init thread */
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
58 NULL, /* exit thread */
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
59 NULL, /* exit process */
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
60 NULL, /* exit master */
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
61 NGX_MODULE_V1_PADDING
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
62 };
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
63
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
64
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
65 static void *
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
66 ngx_google_perftools_create_conf(ngx_cycle_t *cycle)
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
67 {
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
68 ngx_google_perftools_conf_t *gptcf;
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
69
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
70 gptcf = ngx_pcalloc(cycle->pool, sizeof(ngx_google_perftools_conf_t));
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
71 if (gptcf == NULL) {
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
72 return NULL;
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
73 }
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
74
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
75 /*
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
76 * set by pcalloc()
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
77 *
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
78 * gptcf->profiles = { 0, NULL };
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
79 */
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
80
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
81 return gptcf;
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
82 }
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
83
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
84
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
85 static ngx_int_t
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
86 ngx_google_perftools_worker(ngx_cycle_t *cycle)
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
87 {
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
88 u_char *profile;
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
89 ngx_google_perftools_conf_t *gptcf;
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
90
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
91 gptcf = (ngx_google_perftools_conf_t *)
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
92 ngx_get_conf(cycle->conf_ctx, ngx_google_perftools_module);
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
93
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
94 if (gptcf->profiles.len == 0) {
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
95 return NGX_OK;
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
96 }
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
97
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
98 profile = ngx_alloc(gptcf->profiles.len + NGX_INT_T_LEN + 2, cycle->log);
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
99 if (profile == NULL) {
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
100 return NGX_OK;
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
101 }
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
102
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
103 if (getenv("CPUPROFILE")) {
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
104
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
105 /* disable inherited Profiler enabled in master process */
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
106 ProfilerStop();
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
107 }
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
108
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
109 ngx_sprintf(profile, "%V.%d%Z", &gptcf->profiles, ngx_pid);
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
110
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
111 if (ProfilerStart(profile)) {
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
112
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
113 /* start ITIMER_PROF timer */
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
114 ProfilerRegisterThread();
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
115
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
116 } else {
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
117 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_errno,
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
118 "ProfilerStart(%s) failed", profile);
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
119 }
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
120
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
121 ngx_free(profile);
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
122
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
123 return NGX_OK;
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
124 }
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
125
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
126
e5ce4e2de846 ngx_google_perftools_module
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
127 /* ProfilerStop() is called on Profiler destruction */