diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2010-04-14 06:58:30 +0200 |
---|---|---|
committer | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2010-09-10 18:40:06 +1000 |
commit | 69f49ea0d70939340e8a2c28aae36c8e2f3fb41e (patch) | |
tree | 75bb11ec769cd3529084b1da755d97c09a2545d5 | |
parent | 9f4e87b2e7c18243341707a2d2df3957105139e5 (diff) | |
download | busybox-w32-69f49ea0d70939340e8a2c28aae36c8e2f3fb41e.tar.gz busybox-w32-69f49ea0d70939340e8a2c28aae36c8e2f3fb41e.tar.bz2 busybox-w32-69f49ea0d70939340e8a2c28aae36c8e2f3fb41e.zip |
win32: add signal routines and SIGALRM support
The implementation for SIGALRM only because Git needs it
(I think for progress display or something). Probably not hurt
having it. Although the only thing needed here are stubs.
-rw-r--r-- | include/mingw.h | 4 | ||||
-rw-r--r-- | win32/mingw.c | 124 |
2 files changed, 127 insertions, 1 deletions
diff --git a/include/mingw.h b/include/mingw.h index c5f72837b..0ff7f5442 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -109,9 +109,11 @@ struct sigaction { | |||
109 | #define sigemptyset(x) (void)0 | 109 | #define sigemptyset(x) (void)0 |
110 | #define SA_RESTART 0 | 110 | #define SA_RESTART 0 |
111 | 111 | ||
112 | NOIMPL(sigaction,int sig UNUSED_PARAM, struct sigaction *in UNUSED_PARAM, struct sigaction *out UNUSED_PARAM); | 112 | int sigaction(int sig, struct sigaction *in, struct sigaction *out); |
113 | sighandler_t mingw_signal(int sig, sighandler_t handler); | ||
113 | NOIMPL(sigfillset,int *mask UNUSED_PARAM); | 114 | NOIMPL(sigfillset,int *mask UNUSED_PARAM); |
114 | 115 | ||
116 | #define signal mingw_signal | ||
115 | /* | 117 | /* |
116 | * stdio.h | 118 | * stdio.h |
117 | */ | 119 | */ |
diff --git a/win32/mingw.c b/win32/mingw.c index 2b9776175..72e23998c 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -90,3 +90,127 @@ struct passwd *getpwuid(int uid) | |||
90 | p.pw_dir = NULL; | 90 | p.pw_dir = NULL; |
91 | return &p; | 91 | return &p; |
92 | } | 92 | } |
93 | |||
94 | static HANDLE timer_event; | ||
95 | static HANDLE timer_thread; | ||
96 | static int timer_interval; | ||
97 | static int one_shot; | ||
98 | static sighandler_t timer_fn = SIG_DFL; | ||
99 | |||
100 | /* The timer works like this: | ||
101 | * The thread, ticktack(), is a trivial routine that most of the time | ||
102 | * only waits to receive the signal to terminate. The main thread tells | ||
103 | * the thread to terminate by setting the timer_event to the signalled | ||
104 | * state. | ||
105 | * But ticktack() interrupts the wait state after the timer's interval | ||
106 | * length to call the signal handler. | ||
107 | */ | ||
108 | |||
109 | static __stdcall unsigned ticktack(void *dummy UNUSED_PARAM) | ||
110 | { | ||
111 | while (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) { | ||
112 | if (timer_fn == SIG_DFL) | ||
113 | bb_error_msg_and_die("Alarm"); | ||
114 | if (timer_fn != SIG_IGN) | ||
115 | timer_fn(SIGALRM); | ||
116 | if (one_shot) | ||
117 | break; | ||
118 | } | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int start_timer_thread(void) | ||
123 | { | ||
124 | timer_event = CreateEvent(NULL, FALSE, FALSE, NULL); | ||
125 | if (timer_event) { | ||
126 | timer_thread = (HANDLE) _beginthreadex(NULL, 0, ticktack, NULL, 0, NULL); | ||
127 | if (!timer_thread ) { | ||
128 | errno = ENOMEM; | ||
129 | return -1; | ||
130 | } | ||
131 | } else { | ||
132 | errno = ENOMEM; | ||
133 | return -1; | ||
134 | } | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static void stop_timer_thread(void) | ||
139 | { | ||
140 | if (timer_event) | ||
141 | SetEvent(timer_event); /* tell thread to terminate */ | ||
142 | if (timer_thread) { | ||
143 | int rc = WaitForSingleObject(timer_thread, 1000); | ||
144 | if (rc == WAIT_TIMEOUT) | ||
145 | fprintf(stderr, "timer thread did not terminate timely"); | ||
146 | else if (rc != WAIT_OBJECT_0) | ||
147 | fprintf(stderr, "waiting for timer thread failed: %lu", | ||
148 | GetLastError()); | ||
149 | CloseHandle(timer_thread); | ||
150 | } | ||
151 | if (timer_event) | ||
152 | CloseHandle(timer_event); | ||
153 | timer_event = NULL; | ||
154 | timer_thread = NULL; | ||
155 | } | ||
156 | |||
157 | static inline int is_timeval_eq(const struct timeval *i1, const struct timeval *i2) | ||
158 | { | ||
159 | return i1->tv_sec == i2->tv_sec && i1->tv_usec == i2->tv_usec; | ||
160 | } | ||
161 | |||
162 | int setitimer(int type UNUSED_PARAM, struct itimerval *in, struct itimerval *out) | ||
163 | { | ||
164 | static const struct timeval zero; | ||
165 | static int atexit_done; | ||
166 | |||
167 | if (out != NULL) { | ||
168 | errno = EINVAL; | ||
169 | return -1; | ||
170 | } | ||
171 | if (!is_timeval_eq(&in->it_interval, &zero) && | ||
172 | !is_timeval_eq(&in->it_interval, &in->it_value)) { | ||
173 | errno = EINVAL; | ||
174 | return -1; | ||
175 | } | ||
176 | |||
177 | if (timer_thread) | ||
178 | stop_timer_thread(); | ||
179 | |||
180 | if (is_timeval_eq(&in->it_value, &zero) && | ||
181 | is_timeval_eq(&in->it_interval, &zero)) | ||
182 | return 0; | ||
183 | |||
184 | timer_interval = in->it_value.tv_sec * 1000 + in->it_value.tv_usec / 1000; | ||
185 | one_shot = is_timeval_eq(&in->it_interval, &zero); | ||
186 | if (!atexit_done) { | ||
187 | atexit(stop_timer_thread); | ||
188 | atexit_done = 1; | ||
189 | } | ||
190 | return start_timer_thread(); | ||
191 | } | ||
192 | |||
193 | int sigaction(int sig, struct sigaction *in, struct sigaction *out) | ||
194 | { | ||
195 | if (sig != SIGALRM) { | ||
196 | errno = EINVAL; | ||
197 | return -1; | ||
198 | } | ||
199 | if (out != NULL) { | ||
200 | errno = EINVAL; | ||
201 | return -1; | ||
202 | } | ||
203 | |||
204 | timer_fn = in->sa_handler; | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | #undef signal | ||
209 | sighandler_t mingw_signal(int sig, sighandler_t handler) | ||
210 | { | ||
211 | sighandler_t old = timer_fn; | ||
212 | if (sig != SIGALRM) | ||
213 | return signal(sig, handler); | ||
214 | timer_fn = handler; | ||
215 | return old; | ||
216 | } | ||