1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 1997-2018. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20 /*
21 * Purpose: Interrupt handling in windows.
22 */
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26 #include "sys.h"
27 #include "erl_alloc.h"
28 #include "erl_thr_progress.h"
29 #include "erl_driver.h"
30 #include "../../drivers/win32/win_con.h"
31
32 #if defined(__GNUC__)
33 # define WIN_SYS_INLINE __inline__
34 #elif defined(__WIN32__)
35 # define WIN_SYS_INLINE __forceinline
36 #endif
37
38 erts_atomic32_t erts_break_requested;
39 #define ERTS_SET_BREAK_REQUESTED \
40 erts_atomic32_set_nob(&erts_break_requested, (erts_aint32_t) 1)
41 #define ERTS_UNSET_BREAK_REQUESTED \
42 erts_atomic32_set_nob(&erts_break_requested, (erts_aint32_t) 0)
43
44 extern int nohup;
45 HANDLE erts_sys_break_event = NULL;
46
erts_do_break_handling(void)47 void erts_do_break_handling(void)
48 {
49 /*
50 * Most functions that do_break() calls are intentionally not thread safe;
51 * therefore, make sure that all threads but this one are blocked before
52 * proceeding!
53 */
54 erts_thr_progress_block();
55 /* call the break handling function, reset the flag */
56 do_break();
57
58 ResetEvent(erts_sys_break_event);
59 ERTS_UNSET_BREAK_REQUESTED;
60
61 erts_thr_progress_unblock();
62 }
63
64
ctrl_handler_ignore_break(DWORD dwCtrlType)65 BOOL WINAPI ctrl_handler_ignore_break(DWORD dwCtrlType)
66 {
67 switch (dwCtrlType) {
68 case CTRL_C_EVENT:
69 case CTRL_BREAK_EVENT:
70 return TRUE;
71 break;
72 case CTRL_LOGOFF_EVENT:
73 case CTRL_SHUTDOWN_EVENT:
74 if (nohup)
75 return TRUE;
76 /* else pour through... */
77 case CTRL_CLOSE_EVENT:
78 erts_exit(0, "");
79 break;
80 }
81 return TRUE;
82 }
83
erts_set_ignore_break(void)84 void erts_set_ignore_break(void) {
85 ConSetCtrlHandler(ctrl_handler_ignore_break);
86 SetConsoleCtrlHandler(ctrl_handler_ignore_break, TRUE);
87 }
88
ctrl_handler_replace_intr(DWORD dwCtrlType)89 BOOL WINAPI ctrl_handler_replace_intr(DWORD dwCtrlType)
90 {
91 switch (dwCtrlType) {
92 case CTRL_C_EVENT:
93 return FALSE;
94 case CTRL_BREAK_EVENT:
95 SetEvent(erts_sys_break_event);
96 break;
97 case CTRL_LOGOFF_EVENT:
98 if (nohup)
99 return TRUE;
100 /* else pour through... */
101 case CTRL_CLOSE_EVENT:
102 case CTRL_SHUTDOWN_EVENT:
103 erts_exit(0, "");
104 break;
105 }
106 return TRUE;
107 }
108
109
110 /* Don't use ctrl-c for break handler but let it be
111 used by the shell instead (see user_drv.erl) */
erts_replace_intr(void)112 void erts_replace_intr(void) {
113 ConSetCtrlHandler(ctrl_handler_replace_intr);
114 SetConsoleCtrlHandler(ctrl_handler_replace_intr, TRUE);
115 }
116
ctrl_handler(DWORD dwCtrlType)117 BOOL WINAPI ctrl_handler(DWORD dwCtrlType)
118 {
119 switch (dwCtrlType) {
120 case CTRL_C_EVENT:
121 case CTRL_BREAK_EVENT:
122 SetEvent(erts_sys_break_event);
123 break;
124 case CTRL_LOGOFF_EVENT:
125 case CTRL_SHUTDOWN_EVENT:
126 if (nohup)
127 return TRUE;
128 /* else pour through... */
129 case CTRL_CLOSE_EVENT:
130 erts_exit(0, "");
131 break;
132 }
133 return TRUE;
134 }
135
init_break_handler()136 void init_break_handler()
137 {
138 ConSetCtrlHandler(ctrl_handler);
139 SetConsoleCtrlHandler(ctrl_handler, TRUE);
140 }
141
142