source: sources/src/toolsOs.cc @ 1481:a715083df97f

Revision 1481:a715083df97f, 32.7 KB checked in by niam, 21 months ago (diff)

[tools::os] use nanosleep for os::sleep

Line 
1/***************************************************************************
2 *            toolsOs.cc
3 *
4 *  Sat Nov 19 2005
5 *  Copyright  2005  Dmytro Milinevskyy
6 *  milinevskyy@gmail.com
7 ****************************************************************************/
8
9/*
10 *  This program is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU Lesser General Public License version 2.1 as published by
12 *  the Free Software Foundation;
13 *
14 *  This program is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU Library General Public License for more details.
18 *
19 *  You should have received a copy of the GNU Lesser General Public License
20 *  along with this program; if not, write to the Free Software
21 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24/**
25 * vim indentation settings
26 * set tabstop=4
27 * set shiftwidth=4
28 */
29
30#include <libdodo/directives.h>
31
32#include <signal.h>
33#include <pwd.h>
34#include <grp.h>
35#include <unistd.h>
36#include <sys/time.h>
37#include <sys/types.h>
38#include <sys/resource.h>
39#include <sys/wait.h>
40#include <stdlib.h>
41#include <stdio.h>
42#include <errno.h>
43#include <string.h>
44#ifdef PTHREAD_EXT
45#include <pthread.h>
46#endif
47#ifdef DL_EXT
48#include <dlfcn.h>
49#endif
50
51#include <libdodo/pcSyncThread.h>
52#include <libdodo/pcSyncStack.h>
53#include <libdodo/toolsOs.h>
54#include <libdodo/toolsOsEx.h>
55#include <libdodo/types.h>
56#include <libdodo/toolsMisc.h>
57
58using namespace dodo::tools;
59
60#ifdef DL_EXT
61void *os::handlesSig[] = {
62    NULL,
63    NULL,
64    NULL,
65    NULL,
66    NULL,
67    NULL,
68    NULL,
69    NULL,
70    NULL,
71    NULL,
72    NULL,
73    NULL,
74    NULL,
75    NULL,
76    NULL,
77    NULL,
78    NULL,
79    NULL,
80    NULL
81};
82
83//-------------------------------------------------------------------
84
85bool os::handlesOpenedSig[] = {
86    false,
87    false,
88    false,
89    false,
90    false,
91    false,
92    false,
93    false,
94    false,
95    false,
96    false,
97    false,
98    false,
99    false,
100    false,
101    false,
102    false,
103    false,
104    false
105};
106//-------------------------------------------------------------------
107
108char os::handlesCookiesSig[][32] = {
109    {'\0', },
110    {'\0', },
111    {'\0', },
112    {'\0', },
113    {'\0', },
114    {'\0', },
115    {'\0', },
116    {'\0', },
117    {'\0', },
118    {'\0', },
119    {'\0', },
120    {'\0', },
121    {'\0', },
122    {'\0', },
123    {'\0', },
124    {'\0', },
125    {'\0', },
126    {'\0', },
127    {'\0', }
128};
129#endif
130
131//-------------------------------------------------------------------
132
133dodo::pc::sync::thread os::keeper;
134
135//-------------------------------------------------------------------
136
137dodo::string
138os::workingDir()
139{
140    char wd[PATH_MAXLEN];
141
142    if (getcwd(wd, PATH_MAXLEN) == NULL)
143        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_WORKINGDIR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
144
145    return wd;
146}
147
148//-------------------------------------------------------------------
149
150void
151os::setWorkingDir(const dodo::string &path)
152{
153    if (chdir(path.data()) == -1)
154        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETWORKINGDIR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
155}
156
157//-------------------------------------------------------------------
158
159os::__usage__
160os::usage()
161{
162    rusage use;
163    if (getrusage(RUSAGE_SELF, &use) == -1)
164        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_USAGE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
165
166    __usage__ info;
167    info.time = use.ru_utime.tv_sec * 100 + use.ru_utime.tv_usec;
168    info.mem = use.ru_maxrss * 1024;
169
170    return info;
171}
172
173//-------------------------------------------------------------------
174
175void
176os::changeRoot(const dodo::string &path)
177{
178    setWorkingDir(path);
179
180    if (chroot(path.data()) == -1)
181        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_CHANGEROOT, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path);
182}
183
184//-------------------------------------------------------------------
185
186os::__limit__
187os::limit(short type)
188{
189    rlimit limit;
190
191    int realRes(0);
192
193    switch (type) {
194        case LIMIT_CPUTIME:
195
196            realRes = RLIMIT_CPU;
197
198            break;
199
200        case LIMIT_MAXFILESIZE:
201
202            realRes = RLIMIT_FSIZE;
203
204            break;
205
206        case LIMIT_MAXMEMUSAGE:
207
208            realRes = RLIMIT_DATA;
209
210            break;
211
212        case LIMIT_MAXSTACK:
213
214            realRes = RLIMIT_STACK;
215
216            break;
217
218        case LIMIT_MAXPROC:
219
220            realRes = RLIMIT_NPROC;
221
222            break;
223
224        case LIMIT_MAXOPENFILES:
225
226#ifdef __FreeBSD__
227            realRes = RLIMIT_NOFILE;
228#else
229            realRes = RLIMIT_OFILE;
230#endif
231
232            break;
233
234        default:
235
236            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_LIMIT, exception::ERRNO_LIBDODO, OSEX_WRONGPARAMETER, TOOLSOSEX_WRONGPARAMETER_STR, __LINE__, __FILE__);
237    }
238
239    if (getrlimit(realRes, &limit) == -1)
240        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_LIMIT, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
241
242    __limit__ lim;
243
244    lim.current = limit.rlim_cur;
245    lim.max = limit.rlim_max;
246
247    return lim;
248}
249
250//-------------------------------------------------------------------
251
252void
253os::setLimit(short           type,
254             const __limit__ &lim)
255{
256    rlimit limit;
257
258    int realRes(0);
259
260    switch (type) {
261        case LIMIT_CPUTIME:
262
263            realRes = RLIMIT_CPU;
264
265            break;
266
267        case LIMIT_MAXFILESIZE:
268
269            realRes = RLIMIT_FSIZE;
270
271            break;
272
273        case LIMIT_MAXMEMUSAGE:
274
275            realRes = RLIMIT_DATA;
276
277            break;
278
279        case LIMIT_MAXSTACK:
280
281            realRes = RLIMIT_STACK;
282
283            break;
284
285        case LIMIT_MAXPROC:
286
287            realRes = RLIMIT_NPROC;
288
289            break;
290
291        case LIMIT_MAXOPENFILES:
292
293#ifdef __FreeBSD__
294            realRes = RLIMIT_NOFILE;
295#else
296            realRes = RLIMIT_OFILE;
297#endif
298
299            break;
300
301        default:
302
303            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETLIMIT, exception::ERRNO_LIBDODO, OSEX_WRONGPARAMETER, TOOLSOSEX_WRONGPARAMETER_STR, __LINE__, __FILE__);
304    }
305
306    limit.rlim_cur = lim.current;
307    limit.rlim_max = lim.max;
308
309    if (setrlimit(realRes, &limit) == -1)
310        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETLIMIT, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
311}
312
313//-------------------------------------------------------------------
314
315int
316os::priority(short type)
317{
318    int prio = getpriority(PRIO_PROCESS, UID(type));
319    if (prio == -1)
320        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_PRIORITY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
321
322    return prio;
323}
324
325//-------------------------------------------------------------------
326
327void
328os::setPriority(short type,
329                int   prio)
330{
331    if (setpriority(PRIO_PROCESS, UID(type), prio) == -1)
332        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETPRIORITY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
333}
334
335//-------------------------------------------------------------------
336
337int
338os::UID(short type)
339{
340    switch (type) {
341        case ID_UID:
342
343            return getuid();
344
345        case ID_EUID:
346
347            return geteuid();
348
349        default:
350
351            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_UID, exception::ERRNO_LIBDODO, OSEX_WRONGPARAMETER, TOOLSOSEX_WRONGPARAMETER_STR, __LINE__, __FILE__);
352    }
353}
354
355//-------------------------------------------------------------------
356
357void
358os::setUID(short type,
359           int   uid)
360{
361    int res(0);
362
363    switch (type) {
364        case ID_UID:
365
366            res = setuid(uid);
367
368            break;
369
370        case ID_EUID:
371
372            res = seteuid(uid);
373
374            break;
375
376        default:
377
378            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETUID, exception::ERRNO_LIBDODO, OSEX_WRONGPARAMETER, TOOLSOSEX_WRONGPARAMETER_STR, __LINE__, __FILE__);
379    }
380
381    if (res == -1)
382        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETUID, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
383}
384
385//-------------------------------------------------------------------
386
387int
388os::GID(short type)
389{
390    switch (type) {
391        case ID_UID:
392
393            return getgid();
394
395        case ID_EUID:
396
397            return getegid();
398
399        default:
400
401            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_GID, exception::ERRNO_LIBDODO, OSEX_WRONGPARAMETER, TOOLSOSEX_WRONGPARAMETER_STR, __LINE__, __FILE__);
402    }
403}
404
405//-------------------------------------------------------------------
406
407void
408os::setGID(short type,
409           int   uid)
410{
411    int res(0);
412
413    switch (type) {
414        case ID_UID:
415
416            res = setgid(uid);
417
418            break;
419
420        case ID_EUID:
421
422            res = setegid(uid);
423
424            break;
425
426        default:
427
428            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETGID, exception::ERRNO_LIBDODO, OSEX_WRONGPARAMETER, TOOLSOSEX_WRONGPARAMETER_STR, __LINE__, __FILE__);
429    }
430
431    if (res == -1)
432        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETGID, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
433}
434
435//-------------------------------------------------------------------
436
437os::__user__
438os::user(int uid)
439{
440    passwd *in = getpwuid(uid);
441    if (in == NULL)
442        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_USER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
443
444    __user__ info;
445
446    return fillUser(info, in);
447}
448
449//-------------------------------------------------------------------
450
451os::__user__
452os::user(const dodo::string &uid)
453{
454    passwd *in = getpwnam(uid.data());
455    if (in == NULL)
456        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_USER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
457
458    __user__ info;
459
460    return fillUser(info, in);
461}
462
463//-------------------------------------------------------------------
464
465dodoArray<os::__user__>
466os::users()
467{
468    dodoArray<__user__> users;
469
470    passwd *in;
471
472    __user__ info;
473
474    while ((in = getpwent()) != NULL)
475        users.push_back(fillUser(info, in));
476
477    switch (errno) {
478        case EIO:
479        case EMFILE:
480        case ENFILE:
481        case ENOMEM:
482
483            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_USERS, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
484    }
485
486    endpwent();
487
488    return users;
489}
490
491//-------------------------------------------------------------------
492
493os::__user__ &
494os::fillUser(__user__ &info,
495             void     *in)
496{
497    info.gid = ((passwd *)in)->pw_gid;
498    info.home = ((passwd *)in)->pw_dir;
499    info.name = ((passwd *)in)->pw_name;
500    info.pass = ((passwd *)in)->pw_passwd;
501    info.realName = ((passwd *)in)->pw_gecos;
502    info.shell = ((passwd *)in)->pw_shell;
503    info.uid = ((passwd *)in)->pw_uid;
504
505    return info;
506}
507
508//-------------------------------------------------------------------
509
510os::__group__ &
511os::fillGroup(__group__ &info,
512              void      *pw)
513{
514    info.gid = ((::group *)pw)->gr_gid;
515    info.name = ((::group *)pw)->gr_name;
516
517    info.members.clear();
518
519    int i(0);
520
521    while (((::group *)pw)->gr_mem[i] != NULL)
522        info.members.push_back(((::group *)pw)->gr_mem[i++]);
523
524    return info;
525}
526
527//-------------------------------------------------------------------
528
529os::__group__
530os::group(int uid)
531{
532    ::group *in = getgrgid(uid);
533    if (in == NULL)
534        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_GROUP, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
535
536    __group__ info;
537
538    return fillGroup(info, in);
539}
540
541//-------------------------------------------------------------------
542
543os::__group__
544os::group(const dodo::string &uid)
545{
546    ::group *in = getgrnam(uid.data());
547    if (in == NULL)
548        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_GROUP, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
549
550    __group__ info;
551
552    return fillGroup(info, in);
553}
554
555//-------------------------------------------------------------------
556
557dodoArray<os::__group__>
558os::groups()
559{
560    dodoArray<__group__> groups;
561
562    ::group *in;
563
564    __group__ info;
565
566    while ((in = getgrent()) != NULL)
567        groups.push_back(fillGroup(info, in));
568
569    switch (errno) {
570        case EIO:
571        case EMFILE:
572        case ENFILE:
573        case EINTR:
574        case ENOMEM:
575
576            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_GROUPS, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
577    }
578
579    endgrent();
580
581    return groups;
582}
583
584//-------------------------------------------------------------------
585
586void
587os::die(const dodo::string &message,
588        int              status)
589{
590    unsigned short tries = DIE_MAXTRIES;
591
592    while (tries-- > 0)
593        if (fwrite(message.data(), message.size(), 1, stderr) == 1)
594            break;
595    fflush(stderr);
596
597    kill(0, SIGTERM);
598
599    wait(NULL);
600
601    exit(status);
602}
603
604//-------------------------------------------------------------------
605
606void
607os::sleepMs(unsigned long period)
608{
609    timespec ts = {period/1000, (period%1000)*1000000};
610
611    nanosleep(&ts, NULL);
612}
613
614//-------------------------------------------------------------------
615
616void
617os::sleepUs(unsigned long period)
618{
619    timespec ts = {period/1000000, (period%1000000)*1000};
620
621    nanosleep(&ts, NULL);
622}
623
624//-------------------------------------------------------------------
625
626void
627os::sleep(unsigned long period)
628{
629    timespec ts = {period, 0};
630
631    nanosleep(&ts, NULL);
632}
633
634//-------------------------------------------------------------------
635
636void
637os::atExit(void (*func)())
638{
639    if (atexit(func) != 0)
640        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_ATEXIT, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
641}
642
643//-------------------------------------------------------------------
644
645int
646os::PID()
647{
648    return getpid();
649}
650
651//-------------------------------------------------------------------
652
653int
654os::PPID()
655{
656    return getppid();
657}
658
659//-------------------------------------------------------------------
660
661int
662os::GPID()
663{
664    return getpgrp();
665}
666
667//-------------------------------------------------------------------
668
669int
670os::GPID(int pid)
671{
672    int pgid = getpgid(pid);
673    if (pgid == -1)
674        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_GPID, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
675
676    return pgid;
677}
678
679//-------------------------------------------------------------------
680
681void
682os::setGPID(int gpid)
683{
684    if (setpgid(0, gpid) == 1)
685        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETGROUPPID, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
686}
687
688//-------------------------------------------------------------------
689
690void
691os::setGPID(int pid,
692            int gpid)
693{
694    if (setpgid(pid, gpid) == 1)
695        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETGROUPPID, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
696}
697
698//-------------------------------------------------------------------
699
700void
701os::sigMask(void *set,
702            long     blockSignals)
703{
704    if (blockSignals != -1) {
705        if (isSetFlag(blockSignals, SIGNAL_HANGUP))
706            sigaddset((sigset_t *)set, SIGHUP);
707
708        if (isSetFlag(blockSignals, SIGNAL_INTERRUPT))
709            sigaddset((sigset_t *)set, SIGINT);
710
711        if (isSetFlag(blockSignals, SIGNAL_QUIT))
712            sigaddset((sigset_t *)set, SIGQUIT);
713
714        if (isSetFlag(blockSignals, SIGNAL_ILLEGAL_INSTRUCTION))
715            sigaddset((sigset_t *)set, SIGILL);
716
717        if (isSetFlag(blockSignals, SIGNAL_ABORT))
718            sigaddset((sigset_t *)set, SIGABRT);
719
720        if (isSetFlag(blockSignals, SIGNAL_BUS_FAULT))
721            sigaddset((sigset_t *)set, SIGBUS);
722
723        if (isSetFlag(blockSignals, SIGNAL_FLOATINGPOINT_FAULT))
724            sigaddset((sigset_t *)set, SIGFPE);
725
726        if (isSetFlag(blockSignals, SIGNAL_USER_DEFINED1))
727            sigaddset((sigset_t *)set, SIGUSR1);
728
729        if (isSetFlag(blockSignals, SIGNAL_SEGMENTATION_FAULT))
730            sigaddset((sigset_t *)set, SIGSEGV);
731
732        if (isSetFlag(blockSignals, SIGNAL_USER_DEFINED2))
733            sigaddset((sigset_t *)set, SIGUSR2);
734
735        if (isSetFlag(blockSignals, SIGNAL_PIPE_FAULT))
736            sigaddset((sigset_t *)set, SIGPIPE);
737
738        if (isSetFlag(blockSignals, SIGNAL_ALARM))
739            sigaddset((sigset_t *)set, SIGALRM);
740
741        if (isSetFlag(blockSignals, SIGNAL_TERMINATION))
742            sigaddset((sigset_t *)set, SIGTERM);
743
744        if (isSetFlag(blockSignals, SIGNAL_CHILD_CHANGED))
745            sigaddset((sigset_t *)set, SIGCHLD);
746
747        if (isSetFlag(blockSignals, SIGNAL_CONTINUE))
748            sigaddset((sigset_t *)set, SIGCONT);
749
750        if (isSetFlag(blockSignals, SIGNAL_KEYBOARD_STOP))
751            sigaddset((sigset_t *)set, SIGTSTP);
752
753        if (isSetFlag(blockSignals, SIGNAL_CPULIMIT_EXCEEDED))
754            sigaddset((sigset_t *)set, SIGXCPU);
755
756        if (isSetFlag(blockSignals, SIGNAL_FILESIZE_EXCEEDED))
757            sigaddset((sigset_t *)set, SIGXFSZ);
758
759        if (isSetFlag(blockSignals, SIGNAL_BAD_SYSCALL))
760            sigaddset((sigset_t *)set, SIGSYS);
761    }
762}
763
764//-------------------------------------------------------------------
765
766void
767os::setSignalHandler(long          signal,
768                     signalHandler handler,
769                     int           blockSignals)
770{
771    pc::sync::stack tg(&keeper);
772
773#ifdef DL_EXT
774    deinitSignalModule deinit;
775
776    int handleSignal = toSignalNumber(signal);
777    if (handleSignal > 0 && handlesOpenedSig[handleSignal]) {
778        deinit = (deinitSignalModule)dlsym(handlesSig[handleSignal], "deinitToolsOsSignalModule");
779        if (deinit != NULL)
780            deinit(handlesCookiesSig[handleSignal]);
781
782#ifndef DL_FAST
783        dlclose(handlesSig[handleSignal]);
784#endif
785
786        handlesOpenedSig[handleSignal] = false;
787        handlesSig[handleSignal] = NULL;
788    }
789#endif
790
791    struct sigaction act;
792    act.sa_sigaction = (void(*) (int, siginfo_t *, void*))handler;
793    act.sa_flags = SA_SIGINFO | SA_RESTART;
794
795    if (sigemptyset(&act.sa_mask) == -1)
796        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETSIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
797
798    sigMask(&act.sa_mask, blockSignals);
799
800    if (sigaction(os::toRealSignal(signal), &act, NULL) == -1)
801        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETSIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
802}
803
804//-------------------------------------------------------------------
805
806void
807os::setMicroTimer(unsigned long timeout,
808                  signalHandler handler,
809                  int           blockSignals)
810{
811    pc::sync::stack tg(&keeper);
812
813#ifdef DL_EXT
814    deinitSignalModule deinit;
815
816    int handleSignal = toSignalNumber(SIGNAL_ALARM);
817    if (handleSignal > 0 && handlesOpenedSig[handleSignal]) {
818        deinit = (deinitSignalModule)dlsym(handlesSig[handleSignal], "deinitToolsOsSignalModule");
819        if (deinit != NULL)
820            deinit(handlesCookiesSig[handleSignal]);
821
822#ifndef DL_FAST
823        dlclose(handlesSig[handleSignal]);
824#endif
825
826        handlesOpenedSig[handleSignal] = false;
827        handlesSig[handleSignal] = NULL;
828    }
829#endif
830
831    struct sigaction act;
832    act.sa_sigaction = (void(*) (int, siginfo_t *, void*))handler;
833    act.sa_flags = SA_SIGINFO | SA_RESTART;
834
835    if (sigemptyset(&act.sa_mask) == -1)
836        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETMICROTIMER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
837
838    sigMask(&act.sa_mask, blockSignals);
839
840    long tSec = 0, tMicrosec = timeout;
841
842    if (timeout > 1000000) {
843        tSec = timeout / 1000000;
844        tMicrosec = timeout % 1000000;
845    }
846
847    itimerval value;
848    value.it_interval.tv_sec = tSec;
849    value.it_interval.tv_usec = tMicrosec;
850    value.it_value.tv_sec = tSec;
851    value.it_value.tv_usec = tMicrosec;
852
853    if (sigaction(SIGALRM, &act, NULL) == -1)
854        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETMICROTIMER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
855
856    if (setitimer(ITIMER_REAL, &value, NULL) != 0)
857        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETMICROTIMER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
858}
859
860//-------------------------------------------------------------------
861
862void
863os::setTimer(long          timeout,
864             signalHandler handler,
865             int           blockSignals)
866{
867    pc::sync::stack tg(&keeper);
868
869#ifdef DL_EXT
870    deinitSignalModule deinit;
871
872    int handleSignal = toSignalNumber(SIGNAL_ALARM);
873    if (handleSignal > 0 && handlesOpenedSig[handleSignal]) {
874        deinit = (deinitSignalModule)dlsym(handlesSig[handleSignal], "deinitToolsOsSignalModule");
875        if (deinit != NULL)
876            deinit(handlesCookiesSig[handleSignal]);
877
878#ifndef DL_FAST
879        dlclose(handlesSig[handleSignal]);
880#endif
881
882        handlesOpenedSig[handleSignal] = false;
883        handlesSig[handleSignal] = NULL;
884    }
885#endif
886
887    struct sigaction act;
888    act.sa_sigaction = (void(*) (int, siginfo_t *, void*))handler;
889    act.sa_flags = SA_SIGINFO | SA_RESTART;
890
891    if (sigemptyset(&act.sa_mask) == -1)
892        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETTIMER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
893
894    sigMask(&act.sa_mask, blockSignals);
895
896    itimerval value;
897    value.it_interval.tv_sec = timeout;
898    value.it_interval.tv_usec = 0;
899    value.it_value.tv_sec = timeout;
900    value.it_value.tv_usec = 0;
901
902    if (sigaction(SIGALRM, &act, NULL) == -1)
903        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETTIMER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
904
905    if (setitimer(ITIMER_REAL, &value, NULL) != 0)
906        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETTIMER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
907}
908
909//-------------------------------------------------------------------
910
911bool
912os::isSignalHandled(long signal)
913{
914    struct sigaction act;
915    if (sigaction(os::toRealSignal(signal), NULL, &act) == 1)
916        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETSIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
917
918    if (act.sa_sigaction != NULL || act.sa_handler != NULL)
919        return true;
920    else
921        return false;
922}
923
924//-------------------------------------------------------------------
925
926void
927os::sendSignal(int  pid,
928               long signal)
929{
930    if (kill(pid, os::toRealSignal(signal)) == -1)
931        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SENDSIGNAL, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
932}
933
934//-------------------------------------------------------------------
935
936void
937os::removeSignalHandler(long signal)
938{
939    pc::sync::stack tg(&keeper);
940
941#ifdef DL_EXT
942    deinitSignalModule deinit;
943
944    int handleSignal = toSignalNumber(signal);
945    if (handleSignal > 0 && handlesOpenedSig[handleSignal]) {
946        deinit = (deinitSignalModule)dlsym(handlesSig[handleSignal], "deinitToolsOsSignalModule");
947        if (deinit != NULL)
948            deinit(handlesCookiesSig[handleSignal]);
949
950#ifndef DL_FAST
951        dlclose(handlesSig[handleSignal]);
952#endif
953
954        handlesOpenedSig[handleSignal] = false;
955        handlesSig[handleSignal] = NULL;
956    }
957#endif
958
959    struct sigaction act;
960    act.sa_sigaction = NULL;
961
962    if (sigaction(os::toRealSignal(signal), &act, NULL) == 1)
963        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_REMOVESIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
964}
965
966//-------------------------------------------------------------------
967
968#ifdef DL_EXT
969os::__signal_module__
970os::module(const dodo::string &module,
971           void             *toInit)
972{
973#ifdef DL_FAST
974    void *handle = dlopen(module.data(), RTLD_LAZY | RTLD_NODELETE);
975#else
976    void *handle = dlopen(module.data(), RTLD_LAZY);
977#endif
978    if (handle == NULL)
979        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_MODULE, exception::ERRNO_DYNLOAD, 0, dlerror(), __LINE__, __FILE__);
980
981    initSignalModule init = (initSignalModule)dlsym(handle, "initToolsOsSignalModule");
982    if (init == NULL)
983        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_MODULE, exception::ERRNO_DYNLOAD, 0, dlerror(), __LINE__, __FILE__);
984
985    __signal_module__ mod = init(toInit);
986
987    deinitSignalModule deinit = (deinitSignalModule)dlsym(handle, "deinitToolsOsSignalModule");
988    if (init != NULL)
989        deinit(mod.cookie);
990
991
992#ifndef DL_FAST
993    if (dlclose(handle) != 0)
994        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_MODULE, exception::ERRNO_DYNLOAD, 0, dlerror(), __LINE__, __FILE__);
995#endif
996
997    return mod;
998}
999
1000//-------------------------------------------------------------------
1001
1002void
1003os::setSignalHandler(const dodo::string &path,
1004                     void             *toInit)
1005{
1006    pc::sync::stack tg(&keeper);
1007
1008#ifdef DL_FAST
1009    void *handle = dlopen(path.data(), RTLD_LAZY | RTLD_NODELETE);
1010#else
1011    void *handle = dlopen(path.data(), RTLD_LAZY);
1012#endif
1013    if (handle == NULL)
1014        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETSIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1015
1016    initSignalModule init = (initSignalModule)dlsym(handle, "initToolsOsSignalModule");
1017    if (init == NULL)
1018        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETSIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1019
1020    __signal_module__ mod = init(toInit);
1021
1022    deinitSignalModule deinit;
1023
1024    int handleSignal = toSignalNumber(mod.signal);
1025    if (handleSignal > 0 && handlesOpenedSig[handleSignal]) {
1026        deinit = (deinitSignalModule)dlsym(handlesSig[handleSignal], "deinitToolsOsSignalModule");
1027        if (deinit != NULL)
1028            deinit(handlesCookiesSig[handleSignal]);
1029
1030#ifndef DL_FAST
1031        dlclose(handlesSig[handleSignal]);
1032#endif
1033
1034        handlesOpenedSig[handleSignal] = false;
1035        handlesSig[handleSignal] = NULL;
1036    }
1037
1038    handlesSig[handleSignal] = handle;
1039
1040    signalHandler in = (signalHandler)dlsym(handlesSig[mod.signal], mod.hook);
1041    if (in == NULL)
1042        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETSIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1043
1044    struct sigaction act;
1045    act.sa_sigaction = (void(*) (int, siginfo_t *, void*))in;
1046    act.sa_flags = SA_SIGINFO | SA_RESTART;
1047
1048    if (sigemptyset(&act.sa_mask) == -1)
1049        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETSIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1050
1051    sigMask(&act.sa_mask, mod.blockSignals);
1052
1053    if (sigaction(os::toRealSignal(mod.signal), &act, NULL) == 1)
1054        dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETSIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1055
1056    handlesOpenedSig[handleSignal] = true;
1057}
1058#endif
1059
1060//-------------------------------------------------------------------
1061
1062int
1063os::toSignalNumber(long signal)
1064{
1065    switch (signal) {
1066        case SIGNAL_HANGUP:
1067
1068            return 0;
1069
1070        case SIGNAL_INTERRUPT:
1071
1072            return 1;
1073
1074        case SIGNAL_QUIT:
1075
1076            return 2;
1077
1078        case SIGNAL_ILLEGAL_INSTRUCTION:
1079
1080            return 3;
1081
1082        case SIGNAL_ABORT:
1083
1084            return 4;
1085
1086        case SIGNAL_BUS_FAULT:
1087
1088            return 5;
1089
1090        case SIGNAL_FLOATINGPOINT_FAULT:
1091
1092            return 6;
1093
1094        case SIGNAL_USER_DEFINED1:
1095
1096            return 7;
1097
1098        case SIGNAL_SEGMENTATION_FAULT:
1099
1100            return 8;
1101
1102        case SIGNAL_USER_DEFINED2:
1103
1104            return 9;
1105
1106        case SIGNAL_PIPE_FAULT:
1107
1108            return 10;
1109
1110        case SIGNAL_ALARM:
1111
1112            return 11;
1113
1114        case SIGNAL_TERMINATION:
1115
1116            return 12;
1117
1118        case SIGNAL_CHILD_CHANGED:
1119
1120            return 13;
1121
1122        case SIGNAL_CONTINUE:
1123
1124            return 14;
1125
1126        case SIGNAL_KEYBOARD_STOP:
1127
1128            return 15;
1129
1130        case SIGNAL_CPULIMIT_EXCEEDED:
1131
1132            return 16;
1133
1134        case SIGNAL_FILESIZE_EXCEEDED:
1135
1136            return 17;
1137
1138        case SIGNAL_BAD_SYSCALL:
1139
1140            return 18;
1141
1142        default:
1143
1144            return -1;
1145    }
1146}
1147
1148//-------------------------------------------------------------------
1149
1150int
1151os::toRealSignal(long signal)
1152{
1153    switch (signal) {
1154        case SIGNAL_HANGUP:
1155
1156            return SIGHUP;
1157
1158        case SIGNAL_INTERRUPT:
1159
1160            return SIGINT;
1161
1162        case SIGNAL_QUIT:
1163
1164            return SIGQUIT;
1165
1166        case SIGNAL_ILLEGAL_INSTRUCTION:
1167
1168            return SIGILL;
1169
1170        case SIGNAL_ABORT:
1171
1172            return SIGABRT;
1173
1174        case SIGNAL_BUS_FAULT:
1175
1176            return SIGBUS;
1177
1178        case SIGNAL_FLOATINGPOINT_FAULT:
1179
1180            return SIGFPE;
1181
1182        case SIGNAL_USER_DEFINED1:
1183
1184            return SIGUSR1;
1185
1186        case SIGNAL_SEGMENTATION_FAULT:
1187
1188            return SIGSEGV;
1189
1190        case SIGNAL_USER_DEFINED2:
1191
1192            return SIGUSR2;
1193
1194        case SIGNAL_PIPE_FAULT:
1195
1196            return SIGPIPE;
1197
1198        case SIGNAL_ALARM:
1199
1200            return SIGALRM;
1201
1202        case SIGNAL_TERMINATION:
1203
1204            return SIGTERM;
1205
1206        case SIGNAL_CHILD_CHANGED:
1207
1208            return SIGCHLD;
1209
1210        case SIGNAL_CONTINUE:
1211
1212            return SIGCONT;
1213
1214        case SIGNAL_KEYBOARD_STOP:
1215
1216            return SIGTSTP;
1217
1218        case SIGNAL_CPULIMIT_EXCEEDED:
1219
1220            return SIGXCPU;
1221
1222        case SIGNAL_FILESIZE_EXCEEDED:
1223
1224            return SIGXFSZ;
1225
1226        case SIGNAL_BAD_SYSCALL:
1227
1228            return SIGSYS;
1229
1230        default:
1231
1232            return -1;
1233    }
1234}
1235
1236//-------------------------------------------------------------------
1237
1238void
1239os::blockSignal(long signals,
1240                bool block)
1241{
1242    sigset_t signal_mask;
1243    sigemptyset(&signal_mask);
1244
1245    os::sigMask(&signal_mask, signals);
1246
1247    if (block)
1248        sigprocmask(SIG_BLOCK, &signal_mask, NULL);
1249    else
1250        sigprocmask(SIG_UNBLOCK, &signal_mask, NULL);
1251}
1252
1253//-------------------------------------------------------------------
1254
1255void
1256os::daemonize()
1257{
1258    pid_t pid = fork();
1259
1260    if (pid == 0) {
1261        if (setsid() == -1)
1262            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1263
1264        if (close(0) == -1)
1265            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1266        if (close(1) == -1)
1267            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1268        if (close(2) == -1)
1269            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1270
1271        if (chdir("/") == -1)
1272            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1273    } else {
1274        if (pid == -1)
1275            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1276        else
1277            _exit(0);
1278    }
1279}
1280
1281//-------------------------------------------------------------------
1282
1283void
1284os::daemonize(daemon func,
1285              void   *data)
1286{
1287    pid_t pid = fork();
1288
1289    if (pid == 0) {
1290        if (setsid() == -1)
1291            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1292
1293        if (close(0) == -1)
1294            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1295        if (close(1) == -1)
1296            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1297        if (close(2) == -1)
1298            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1299
1300        if (chdir("/") == -1)
1301            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1302
1303        func(data);
1304
1305        exit(0);
1306    } else {
1307        if (pid == -1)
1308            dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__);
1309        else
1310            _exit(0);
1311    }
1312}
1313
1314//-------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.