Implement shmlog command
Patch status: needinfo
Patch by Alexander Berntsen
Long description:
Add shmlog command that takes <size>|toggle|on|off. Separate logbuffer management into open_logbuffer() and close_logbuffer(). Make t/187-commands-parser.t expect 'shmlog'. Add update_shmlog_atom() to update the SHMLOG_PATH.
To apply this patch, use:
curl http://cr.i3wm.org/patch/176/raw.patch | git am
b/include/commands.h
24 |
@@ -271,4 +271,10 @@ void cmd_rename_workspace(I3_CMD, char *old_name, char *new_name); |
25 |
*/ |
26 |
void cmd_bar(I3_CMD, char *bar_type, char *bar_value, char *bar_id); |
27 |
|
28 |
+/* |
29 |
+ * Implementation of 'shmlog <size>|toggle|on|off' |
30 |
+ * |
31 |
+ */ |
32 |
+void cmd_shmlog(I3_CMD, char *argument); |
33 |
+ |
34 |
#endif |
b/include/log.h
39 |
@@ -39,6 +39,18 @@ extern int shmlog_size; |
40 |
void init_logging(void); |
41 |
|
42 |
/** |
43 |
+ * Opens the logbuffer. |
44 |
+ * |
45 |
+ */ |
46 |
+void open_logbuffer(void); |
47 |
+ |
48 |
+/** |
49 |
+ * Closes the logbuffer. |
50 |
+ * |
51 |
+ */ |
52 |
+void close_logbuffer(void); |
53 |
+ |
54 |
+/** |
55 |
* Set debug logging. |
56 |
* |
57 |
*/ |
b/include/x.h
62 |
@@ -109,6 +109,12 @@ void x_raise_con(Con *con, bool above_all); |
63 |
void x_set_name(Con *con, const char *name); |
64 |
|
65 |
/** |
66 |
+ * Set up the SHMLOG_PATH atom. |
67 |
+ * |
68 |
+ */ |
69 |
+void update_shmlog_atom(void); |
70 |
+ |
71 |
+/** |
72 |
* Sets up i3 specific atoms (I3_SOCKET_PATH and I3_CONFIG_PATH) |
73 |
* |
74 |
*/ |
b/parser-specs/commands.spec
79 |
@@ -19,6 +19,7 @@ state INITIAL: |
80 |
'exit' -> call cmd_exit() |
81 |
'restart' -> call cmd_restart() |
82 |
'reload' -> call cmd_reload() |
83 |
+ 'shmlog' -> SHMLOG |
84 |
'border' -> BORDER |
85 |
'layout' -> LAYOUT |
86 |
'append_layout' -> APPEND_LAYOUT |
87 |
@@ -62,6 +63,12 @@ state EXEC: |
88 |
command = string |
89 |
-> call cmd_exec($nosn, $command) |
90 |
|
91 |
+# shmlog <size>|toggle|on|off |
92 |
+state SHMLOG: |
93 |
+ # argument may be a number |
94 |
+ argument = string |
95 |
+ -> call cmd_shmlog($argument) |
96 |
+ |
97 |
# border normal|none|1pixel|toggle|1pixel |
98 |
state BORDER: |
99 |
border_style = 'normal', 'pixel' |
b/src/commands.c
104 |
@@ -13,6 +13,7 @@ |
105 |
#include <stdarg.h> |
106 |
|
107 |
#include "all.h" |
108 |
+#include "shmlog.h" |
109 |
|
110 |
// Macros to make the YAJL API a bit easier to use. |
111 |
#define y(x, ...) yajl_gen_ ## x (cmd_output->json_gen, ##__VA_ARGS__) |
112 |
@@ -2027,3 +2028,28 @@ void cmd_bar(I3_CMD, char *bar_type, char *bar_value, char *bar_id) { |
113 |
|
114 |
update_barconfig(); |
115 |
} |
116 |
+ |
117 |
+/* |
118 |
+ * Implementation of 'shmlog <size>|toggle|on|off' |
119 |
+ * |
120 |
+ */ |
121 |
+void cmd_shmlog(I3_CMD, char *argument) { |
122 |
+ if (!strcmp(argument,"toggle")) |
123 |
+ /* Toggle if default is not 0. If it is 0, set to default. */ |
124 |
+ shmlog_size = shmlog_size ? -shmlog_size : default_shmlog_size; |
125 |
+ else if (!strcmp(argument, "off")) |
126 |
+ shmlog_size = 0; |
127 |
+ else if (!strcmp(argument, "on")) |
128 |
+ shmlog_size = default_shmlog_size; |
129 |
+ else { |
130 |
+ /* Restart logging with the new size in the argument. */ |
131 |
+ shmlog_size = 0; |
132 |
+ LOG("Restarting shm logging...\n"); |
133 |
+ init_logging(); |
134 |
+ shmlog_size = atoi(argument); |
135 |
+ } |
136 |
+ LOG("%s shm logging\n", shmlog_size > 0 ? "Enabling" : "Disabling"); |
137 |
+ init_logging(); |
138 |
+ update_shmlog_atom(); |
139 |
+ ysuccess(true); |
140 |
+} |
b/src/log.c
145 |
@@ -89,10 +89,21 @@ void init_logging(void) { |
146 |
} |
147 |
} |
148 |
} |
149 |
+ /* Start SHM logging if shmlog_size is > 0. shmlog_size is SHMLOG_SIZE by |
150 |
+ * default on development versions, and 0 on release versions. If it is |
151 |
+ * not > 0, the user has turned it off, so let's close the logbuffer. */ |
152 |
+ if (shmlog_size > 0 && logbuffer == NULL) |
153 |
+ open_logbuffer(); |
154 |
+ else if (shmlog_size <= 0 && logbuffer) |
155 |
+ close_logbuffer(); |
156 |
+ atexit(purge_zerobyte_logfile); |
157 |
+} |
158 |
|
159 |
- /* If this is a debug build (not a release version), we will enable SHM |
160 |
- * logging by default, unless the user turned it off explicitly. */ |
161 |
- if (logbuffer == NULL && shmlog_size > 0) { |
162 |
+/* |
163 |
+ * Opens the logbuffer. |
164 |
+ * |
165 |
+ */ |
166 |
+void open_logbuffer(void) { |
167 |
/* Reserve 1% of the RAM for the logfile, but at max 25 MiB. |
168 |
* For 512 MiB of RAM this will lead to a 5 MiB log buffer. |
169 |
* At the moment (2011-12-10), no testcase leads to an i3 log |
170 |
@@ -127,10 +138,8 @@ void init_logging(void) { |
171 |
|
172 |
logbuffer = mmap(NULL, logbuffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, logbuffer_shm, 0); |
173 |
if (logbuffer == MAP_FAILED) { |
174 |
- close(logbuffer_shm); |
175 |
- shm_unlink(shmlogname); |
176 |
+ close_logbuffer(); |
177 |
fprintf(stderr, "Could not mmap SHM segment for the i3 log: %s\n", strerror(errno)); |
178 |
- logbuffer = NULL; |
179 |
return; |
180 |
} |
181 |
|
182 |
@@ -148,8 +157,16 @@ void init_logging(void) { |
183 |
logwalk = logbuffer + sizeof(i3_shmlog_header); |
184 |
loglastwrap = logbuffer + logbuffer_size; |
185 |
store_log_markers(); |
186 |
- } |
187 |
- atexit(purge_zerobyte_logfile); |
188 |
+} |
189 |
+ |
190 |
+/* |
191 |
+ * Closes the logbuffer. |
192 |
+ * |
193 |
+ */ |
194 |
+void close_logbuffer(void) { |
195 |
+ close(logbuffer_shm); |
196 |
+ shm_unlink(shmlogname); |
197 |
+ logbuffer = NULL; |
198 |
} |
199 |
|
200 |
/* |
b/src/x.c
205 |
@@ -1064,6 +1064,16 @@ void x_set_name(Con *con, const char *name) { |
206 |
} |
207 |
|
208 |
/* |
209 |
+ * Set up the I3_SHMLOG_PATH atom. |
210 |
+ * |
211 |
+ */ |
212 |
+void update_shmlog_atom() { |
213 |
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, |
214 |
+ A_I3_SHMLOG_PATH, A_UTF8_STRING, 8, |
215 |
+ strlen(shmlogname), shmlogname); |
216 |
+} |
217 |
+ |
218 |
+/* |
219 |
* Sets up i3 specific atoms (I3_SOCKET_PATH and I3_CONFIG_PATH) |
220 |
* |
221 |
*/ |
222 |
@@ -1075,8 +1085,7 @@ void x_set_i3_atoms(void) { |
223 |
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A_I3_PID, XCB_ATOM_CARDINAL, 32, 1, &pid); |
224 |
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A_I3_CONFIG_PATH, A_UTF8_STRING, 8, |
225 |
strlen(current_configpath), current_configpath); |
226 |
- xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, A_I3_SHMLOG_PATH, A_UTF8_STRING, 8, |
227 |
- strlen(shmlogname), shmlogname); |
228 |
+ update_shmlog_atom(); |
229 |
} |
230 |
|
231 |
/* |
b/testcases/t/187-commands-parser.t
236 |
@@ -144,7 +144,7 @@ is(parser_calls("\nworkspace test"), |
237 |
################################################################################ |
238 |
|
239 |
is(parser_calls('unknown_literal'), |
240 |
- "ERROR: Expected one of these tokens: <end>, '[', 'move', 'exec', 'exit', 'restart', 'reload', 'border', 'layout', 'append_layout', 'workspace', 'focus', 'kill', 'open', 'fullscreen', 'split', 'floating', 'mark', 'resize', 'rename', 'nop', 'scratchpad', 'mode', 'bar'\n" . |
241 |
+ "ERROR: Expected one of these tokens: <end>, '[', 'move', 'exec', 'exit', 'restart', 'reload', 'shmlog', 'border', 'layout', 'append_layout', 'workspace', 'focus', 'kill', 'open', 'fullscreen', 'split', 'floating', 'mark', 'resize', 'rename', 'nop', 'scratchpad', 'mode', 'bar'\n" . |
242 |
"ERROR: Your command: unknown_literal\n" . |
243 |
"ERROR: ^^^^^^^^^^^^^^^", |
244 |
'error for unknown literal ok'); |