mirror of
https://github.com/git/git.git
synced 2026-03-13 18:33:25 +01:00
Implement setitimer() and sigaction().
The timer is implemented using a thread. Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
This commit is contained in:
116
compat/mingw.c
116
compat/mingw.c
@@ -650,3 +650,119 @@ struct passwd *mingw_getpwuid(int uid)
|
||||
p.pw_dir = NULL;
|
||||
return &p;
|
||||
}
|
||||
|
||||
|
||||
static HANDLE timer_event;
|
||||
static HANDLE timer_thread;
|
||||
static int timer_interval;
|
||||
static int one_shot;
|
||||
static sig_handler_t timer_fn = SIG_DFL;
|
||||
|
||||
/* The timer works like this:
|
||||
* The thread, ticktack(), is basically a trivial routine that most of the
|
||||
* time only waits to receive the signal to terminate. The main thread
|
||||
* tells the thread to terminate by setting the timer_event to the signalled
|
||||
* state.
|
||||
* But ticktack() does not wait indefinitely; instead, it interrupts the
|
||||
* wait state every now and then, namely exactly after timer's interval
|
||||
* length. At these opportunities it calls the signal handler.
|
||||
*/
|
||||
|
||||
static __stdcall unsigned ticktack(void *dummy)
|
||||
{
|
||||
while (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) {
|
||||
if (timer_fn == SIG_DFL)
|
||||
die("Alarm");
|
||||
if (timer_fn != SIG_IGN)
|
||||
timer_fn(SIGALRM);
|
||||
if (one_shot)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int start_timer_thread(void)
|
||||
{
|
||||
timer_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (timer_event) {
|
||||
timer_thread = (HANDLE) _beginthreadex(NULL, 0, ticktack, NULL, 0, NULL);
|
||||
if (!timer_thread )
|
||||
return errno = ENOMEM,
|
||||
error("cannot create progress indicator");
|
||||
} else
|
||||
return errno = ENOMEM,
|
||||
error("cannot allocate resources for progress indicator");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stop_timer_thread(void)
|
||||
{
|
||||
if (timer_event)
|
||||
SetEvent(timer_event); /* tell thread to terminate */
|
||||
if (timer_thread) {
|
||||
int rc = WaitForSingleObject(timer_thread, 1000);
|
||||
if (rc == WAIT_TIMEOUT)
|
||||
error("timer thread did not terminate timely");
|
||||
else if (rc != WAIT_OBJECT_0)
|
||||
error("waiting for timer thread failed: %lu",
|
||||
GetLastError());
|
||||
CloseHandle(timer_thread);
|
||||
}
|
||||
if (timer_event)
|
||||
CloseHandle(timer_event);
|
||||
timer_event = NULL;
|
||||
timer_thread = NULL;
|
||||
}
|
||||
|
||||
static inline int is_timeval_eq(const struct timeval *i1, const struct timeval *i2)
|
||||
{
|
||||
return i1->tv_sec == i2->tv_sec && i1->tv_usec == i2->tv_usec;
|
||||
}
|
||||
|
||||
int setitimer(int type, struct itimerval *in, struct itimerval *out)
|
||||
{
|
||||
static const struct timeval zero;
|
||||
|
||||
if (out != NULL)
|
||||
return errno = EINVAL,
|
||||
error("setitmer param 3 != NULL not implemented");
|
||||
if (!is_timeval_eq(&in->it_interval, &zero) &&
|
||||
!is_timeval_eq(&in->it_interval, &in->it_value))
|
||||
return errno = EINVAL,
|
||||
error("setitmer: it_interval must be zero or eq it_value");
|
||||
|
||||
if (timer_thread)
|
||||
stop_timer_thread();
|
||||
|
||||
if (is_timeval_eq(&in->it_value, &zero) &&
|
||||
is_timeval_eq(&in->it_interval, &zero))
|
||||
return 0;
|
||||
|
||||
timer_interval = in->it_interval.tv_sec * 1000 + in->it_interval.tv_usec / 1000;
|
||||
one_shot = is_timeval_eq(&in->it_value, &zero);
|
||||
atexit(stop_timer_thread);
|
||||
return start_timer_thread();
|
||||
}
|
||||
|
||||
int sigaction(int sig, struct sigaction *in, struct sigaction *out)
|
||||
{
|
||||
if (sig != SIGALRM)
|
||||
return errno = EINVAL,
|
||||
error("sigaction only implemented for SIGALRM");
|
||||
if (out != NULL)
|
||||
return errno = EINVAL,
|
||||
error("sigaction: param 3 != NULL not implemented");
|
||||
|
||||
timer_fn = in->sa_handler;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef signal
|
||||
sig_handler_t mingw_signal(int sig, sig_handler_t handler)
|
||||
{
|
||||
if (sig != SIGALRM)
|
||||
return signal(sig, handler);
|
||||
sig_handler_t old = timer_fn;
|
||||
timer_fn = handler;
|
||||
return old;
|
||||
}
|
||||
|
||||
@@ -454,7 +454,6 @@ typedef int pid_t;
|
||||
#define WNOHANG 1
|
||||
#define SIGKILL 0
|
||||
#define SIGCHLD 0
|
||||
#define SIGALRM 0
|
||||
#define SIGPIPE 0
|
||||
#define ECONNABORTED 0
|
||||
|
||||
@@ -548,6 +547,24 @@ struct passwd *mingw_getpwuid(int uid);
|
||||
static inline int getuid() { return 1; }
|
||||
static inline struct passwd *getpwnam(const char *name) { return NULL; }
|
||||
|
||||
struct itimerval {
|
||||
struct timeval it_value, it_interval;
|
||||
};
|
||||
int setitimer(int type, struct itimerval *in, struct itimerval *out);
|
||||
#define ITIMER_REAL 0
|
||||
|
||||
typedef void (__cdecl *sig_handler_t)(int);
|
||||
struct sigaction {
|
||||
sig_handler_t sa_handler;
|
||||
unsigned sa_flags;
|
||||
};
|
||||
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
|
||||
#define sigemptyset(x) (void)0
|
||||
#define SA_RESTART 0
|
||||
#define SIGALRM 100
|
||||
sig_handler_t mingw_signal(int sig, sig_handler_t handler);
|
||||
#define signal mingw_signal
|
||||
|
||||
#endif /* __MINGW32__ */
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user