Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Unix Abstraction Layer
0003  *
0004  * @file sys_unix.h
0005  */
0006 /* -----------------------------------------------------------------------------
0007  * Enduro/X Middleware Platform for Distributed Transaction Processing
0008  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0009  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0010  * This software is released under one of the following licenses:
0011  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0012  * See LICENSE file for full text.
0013  * -----------------------------------------------------------------------------
0014  * AGPL license:
0015  *
0016  * This program is free software; you can redistribute it and/or modify it under
0017  * the terms of the GNU Affero General Public License, version 3 as published
0018  * by the Free Software Foundation;
0019  *
0020  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0021  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0022  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0023  * for more details.
0024  *
0025  * You should have received a copy of the GNU Affero General Public License along 
0026  * with this program; if not, write to the Free Software Foundation, Inc.,
0027  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0028  *
0029  * -----------------------------------------------------------------------------
0030  * A commercial use license is available from Mavimax, Ltd
0031  * contact@mavimax.com
0032  * -----------------------------------------------------------------------------
0033  */
0034 #ifndef SYS_UNIX_H
0035 #define SYS_UNIX_H
0036 
0037 #ifdef  __cplusplus
0038 extern "C" {
0039 #endif
0040 /*---------------------------Includes-----------------------------------*/
0041 #include <ndrx_config.h>
0042 #include <stdint.h>
0043 #include <regex.h>
0044 #include <sys_primitives.h>
0045 #include <ubf.h>
0046 #include <atmi.h>
0047 #include <exhash.h>
0048 #include <nstdutil.h>
0049     
0050 #ifdef EX_OS_DARWIN
0051 #include <sys/types.h>
0052 #include <sys/_types/_timespec.h>
0053 #include <mach/mach.h>
0054 #include <mach/clock.h>
0055 #endif
0056     
0057 #include <sys_mqueue.h>
0058     
0059 #if defined(EX_USE_SYSVQ) || defined(EX_USE_SVAPOLL)
0060     
0061 /* Feature #281 */
0062 #include <sys_svq.h>
0063 #include <poll.h>
0064 
0065 #elif defined(EX_USE_EPOLL)
0066 #include <sys/epoll.h>
0067 #elif defined(EX_USE_KQUEUE)
0068 #include <sys/event.h>
0069 #else
0070 #include <poll.h>
0071 #endif
0072 
0073 /*---------------------------Externs------------------------------------*/
0074 /*---------------------------Macros-------------------------------------*/
0075 
0076 #define NDRX_POLLEXCL_POLICY    "POLLEXCL_POLICY"   /**< for aix svapoll, policy flag */
0077 #define NDRX_POLLEXCL_POLICY_DFLT    "ONE"         /**< for aix svapoll, policy value */
0078 
0079 #if defined(EX_USE_SYSVQ) || defined(EX_USE_SVAPOLL)
0080     
0081 #define EX_EPOLL_CTL_ADD        1
0082 #define EX_EPOLL_CTL_DEL        2
0083     
0084 #define EX_EPOLL_FLAGS          POLLIN
0085     
0086 #elif defined(EX_USE_EPOLL)
0087 
0088 #define EX_EPOLL_CTL_ADD        EPOLL_CTL_ADD
0089 #define EX_EPOLL_CTL_DEL        EPOLL_CTL_DEL
0090     
0091 #define EX_EPOLL_FLAGS          (EPOLLIN | EPOLLERR | EPOLLEXCLUSIVE)
0092 
0093 #elif defined (EX_USE_KQUEUE)
0094 
0095 #define EX_EPOLL_CTL_ADD        1
0096 #define EX_EPOLL_CTL_DEL        2
0097     
0098 /* #define EX_EPOLL_FLAGS          EV_ADD | EV_ONESHOT | EV_ENABLE */
0099 #define EX_EPOLL_FLAGS          EV_ADD
0100     
0101 #else
0102 
0103 #define EX_EPOLL_CTL_ADD        1
0104 #define EX_EPOLL_CTL_DEL        2
0105     
0106 #define EX_EPOLL_FLAGS          POLLIN
0107 
0108 #endif
0109 
0110 #ifdef EX_OS_DARWIN
0111 
0112 /* The opengroup spec isn't clear on the mapping from REALTIME to CALENDAR
0113  being appropriate or not.
0114  http://pubs.opengroup.org/onlinepubs/009695299/basedefs/time.h.html */
0115 
0116 #ifndef CLOCK_MONOTONIC
0117 
0118 /* XXX only supports a single timer */
0119 #define TIMER_ABSTIME -1
0120 #define CLOCK_REALTIME CALENDAR_CLOCK
0121 #define CLOCK_MONOTONIC SYSTEM_CLOCK
0122 
0123 
0124 #else
0125 
0126 /* clocks defined */
0127 #define EX_OS_DARWIN_HAVE_CLOCK 1
0128 
0129 #endif
0130     
0131 #define NDRX_OSX_COND_FIX_ATTEMPTS      100 /**< to avoid race condition */
0132 
0133 #endif
0134     
0135 #define EX_KILL_SLEEP_SECS 2
0136 /******************************************************************************/
0137 /***************************** PROGNAME ***************************************/
0138 /******************************************************************************/
0139 /**
0140  * Configure the program name.
0141  * On same platforms/gcc versions we have __progname external
0142  * On other systems we will do lookup by ps function
0143  */    
0144 #ifdef HAVE_PROGNAME
0145     
0146 extern NDRX_API const char * __progname;
0147 
0148 #define EX_PROGNAME __progname
0149 
0150 
0151 #elif EX_OS_AIX
0152 
0153 #define EX_PROGNAME ndrx_sys_get_proc_name_getprocs()
0154 
0155 #else
0156 
0157 /* the worst option: to use ps, it generates sigchild...
0158  * and for libraries that is not good.
0159  */
0160 #define EX_PROGNAME ndrx_sys_get_proc_name_by_ps()
0161 
0162 #endif
0163 
0164 /******************************************************************************/
0165 /***************************** PROCESS TESTING ********************************/
0166 /******************************************************************************/
0167 /**
0168  * The best option is linux procfs, we generally fallback to kill -0
0169  * but better would be to use OS options for providing pid + procname testing 
0170  * for existence. Because OS might reuse the PID.
0171  */
0172 #ifdef EX_OS_LINUX
0173 
0174 #define ndrx_sys_is_process_running ndrx_sys_is_process_running_procfs
0175 
0176 #elif EX_OS_CYGWIN
0177 
0178 /* Same as for linux */
0179 #define ndrx_sys_is_process_running ndrx_sys_is_process_running_procfs
0180 
0181 #else
0182 
0183 #define ndrx_sys_is_process_running ndrx_sys_is_process_running_by_kill
0184 
0185 #endif
0186  
0187 /******************************************************************************/
0188 
0189 #define NDRX_SV_RESTYPE_SHM     1   /**< Shared mem requested           */
0190 #define NDRX_SV_RESTYPE_SEM     2   /**< Semaphores requested           */
0191 #define NDRX_SV_RESTYPE_QUE     3   /**< Queues requested               */
0192 /*---------------------------Enums--------------------------------------*/
0193 /*---------------------------Typedefs-----------------------------------*/
0194     
0195 /**
0196  * (E)poll data
0197  */
0198 typedef union ndrx_epoll_data {
0199     void    *ptr;
0200     int      fd;
0201     uint32_t u32;
0202     uint64_t u64;
0203     mqd_t    mqd;
0204 } ndrx_epoll_data_t;
0205 
0206 /**
0207  * (E)poll event
0208  */
0209 struct ndrx_epoll_event {
0210 
0211     uint32_t     events;    /* Epoll events */
0212 
0213     ndrx_epoll_data_t data;      /* User data variable */
0214 
0215     /* The structure generally is the same as for linux epoll_wait
0216      * This bellow is extension for non linux version.
0217      */
0218     #ifndef EX_USE_EPOLL
0219     int         is_mqd;      /* Set to TRUE, if call is for message q */
0220     #endif
0221 };
0222 
0223 /**
0224  * Memory infos...
0225  */
0226 typedef struct ndrx_proc_info ndrx_proc_info_t;
0227 struct ndrx_proc_info
0228 {
0229     long rss;   /**< resident memory in kilobytes       */
0230     long vsz;   /**< virtual memory in kilobytes        */
0231 };
0232 
0233 /**
0234  * System V resource ID
0235  */
0236 typedef struct mdrx_sysv_res mdrx_sysv_res_t;
0237 struct mdrx_sysv_res
0238 {
0239     int restyp; /**< See NDRX_SV_RESTYPE        */
0240     int id;     /**< Resource ID                */
0241     int key;    /**< Resource Key               */
0242 };
0243 
0244 #ifdef EX_OS_DARWIN
0245 
0246 #ifndef EX_OS_DARWIN_HAVE_CLOCK
0247 typedef int clockid_t;
0248 #endif
0249 
0250 
0251 /**
0252  * See https://www.endurox.org/issues/512
0253  * dirty access to busy field, due to macos pthread lib bug 
0254  */
0255 typedef struct {
0256     long sig;
0257     uint32_t lock;
0258     uint32_t unused;
0259     char *busy;
0260 } ndrx_osx_pthread_cond_t;
0261 
0262 #endif
0263 
0264 #ifdef EX_USE_SVAPOLL
0265 
0266 #ifndef EX_OS_AIX
0267 
0268 /**
0269  * Use for linux dev build only...
0270  * not functional, to simulate aix
0271  */
0272 struct  ndrx_pollmsg
0273 {
0274     int       msgid;      /**< message queue id */
0275     short     reqevents;  /**< requested events */
0276     short     rtnevents;  /**< returned events  */
0277 };
0278 
0279 /**
0280  * Use for linux dev build only...
0281  * not functional, to simulate aix
0282  */
0283 struct  ndrx_pollfd
0284 {
0285     int    fd;          /**< file descriptor */
0286     short  events;      /**< requested events */
0287     short  revents;     /**< returned events */
0288 };
0289 
0290 /* just for build */
0291 #define NFDS(x)         0
0292 #define NMSGS(x)        0
0293 
0294 #else
0295 
0296 /* in aix just use direct defines */
0297 #define ndrx_pollmsg pollmsg
0298 #define ndrx_pollfd pollfd
0299 
0300 
0301 #endif
0302 
0303 #endif
0304 /*---------------------------Globals------------------------------------*/
0305 /*---------------------------Statics------------------------------------*/
0306 /*---------------------------Prototypes---------------------------------*/
0307 
0308 #if defined(EX_OS_DARWIN) && !defined(EX_OS_DARWIN_HAVE_CLOCK)
0309 extern int clock_gettime(clockid_t clk_id, struct timespec *tp);
0310 #endif
0311 
0312 
0313 #if 1==EX_OS_SUNOS
0314 
0315 extern NDRX_API ssize_t sol_mq_timedreceive(mqd_t mqdes, char *msg_ptr,
0316      size_t  msg_len,  unsigned  *msg_prio, struct
0317      timespec *abs_timeout);
0318 extern NDRX_API int sol_mq_timedsend(mqd_t mqdes, char *msg_ptr, size_t len, 
0319                               unsigned int msg_prio, struct timespec *abs_timeout);
0320 extern NDRX_API int sol_mq_unlink(char *name);
0321 extern NDRX_API int sol_mq_setattr(mqd_t mqdes,
0322                        struct mq_attr * newattr,
0323                        struct mq_attr * oldattr);
0324 extern NDRX_API int sol_mq_send(mqd_t mqdes, char *msg_ptr, size_t msg_len,
0325                     unsigned int msg_prio);
0326 extern NDRX_API ssize_t sol_mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, 
0327                                 unsigned int *msg_prio);
0328 extern NDRX_API mqd_t sol_mq_open(char *name, int oflag, mode_t mode, struct mq_attr *attr);
0329 extern NDRX_API int sol_mq_notify(mqd_t mqdes, struct sigevent * sevp);
0330 extern NDRX_API int sol_mq_getattr(mqd_t mqdes, struct mq_attr * attr);
0331 extern NDRX_API int sol_mq_close(mqd_t mqdes);
0332 
0333 
0334 #endif
0335 
0336 #if defined(EX_OS_DARWIN) || defined(EX_OS_FREEBSD)
0337 extern NDRX_API FILE * fmemopen(void *buffer, size_t len, const char *mode);
0338 #endif
0339 
0340 /* poll ops */
0341 extern NDRX_API void ndrx_epoll_mainq_set(char *qstr);
0342 extern NDRX_API mqd_t ndrx_epoll_service_add(char *svcnm, int idx, mqd_t mq_exits);
0343 extern NDRX_API int ndrx_epoll_shallopenq(int idx);
0344 extern NDRX_API int ndrx_epoll_resid_get(void);
0345 
0346 extern NDRX_API int ndrx_epoll_sys_init(void);
0347 extern NDRX_API void ndrx_epoll_sys_uninit(void);
0348 extern NDRX_API char * ndrx_epoll_mode(void);
0349 extern NDRX_API int ndrx_epoll_ctl(int epfd, int op, int fd, struct ndrx_epoll_event *event);
0350 extern NDRX_API int ndrx_epoll_ctl_mq(int epfd, int op, mqd_t fd, struct ndrx_epoll_event *event);
0351 extern NDRX_API int ndrx_epoll_create(int size);
0352 extern NDRX_API int ndrx_epoll_close(int fd);
0353 extern NDRX_API int ndrx_epoll_wait(int epfd, struct ndrx_epoll_event *events, 
0354         int maxevents, int timeout, char **buf, int *buf_len);
0355 extern NDRX_API int ndrx_epoll_errno(void);
0356 extern NDRX_API char * ndrx_poll_strerror(int err);
0357 
0358 /* used by System V, dummies for others pollers/queues: */
0359 extern NDRX_API int ndrx_epoll_resid_get(void);
0360 extern NDRX_API int ndrx_epoll_down(int force);
0361 extern NDRX_API int ndrx_epoll_shmdetach(void);
0362 extern NDRX_API int ndrx_epoll_service_translate(char *send_q, char *q_prefix, 
0363         char *svc, int resid);
0364 extern NDRX_API void ndrx_epoll_mainq_set(char *qstr);
0365 extern NDRX_API int ndrx_epoll_shallopenq(int idx);
0366 extern NDRX_API mqd_t ndrx_epoll_service_add(char *svcnm, int idx, mqd_t mq_exits);
0367 
0368 /* string generics: */
0369 
0370 extern NDRX_API void ndrx_string_hash_free(string_hash_t *h);
0371 extern NDRX_API string_hash_t * ndrx_string_hash_add(string_hash_t **h, char *str);
0372 extern NDRX_API string_hash_t * ndrx_string_hash_add_cnt(string_hash_t **h, char *str);
0373 extern NDRX_API string_hash_t * ndrx_string_hash_get(string_hash_t *h, char *str);
0374 
0375 extern NDRX_API char *ndrx_sys_get_cur_username(void);
0376 extern NDRX_API int ndrx_sys_get_hostname(char *out_hostname, long out_bufsz);
0377 extern NDRX_API string_list_t * ndrx_sys_ps_list(char *filter1, char *filter2, 
0378         char *filter3, char *filter4, char *regex1);
0379 extern NDRX_API string_list_t * ndrx_sys_ps_getchilds(pid_t ppid);
0380 extern NDRX_API string_list_t* ndrx_sys_folder_list(char *path, int *return_status);
0381 
0382 extern NDRX_API int ndrx_sys_ps_list2hash(string_list_t *plist, ndrx_intmap_t **hash);
0383 extern NDRX_API int ndrx_sys_ps_hash2parents(ndrx_intmap_t **pshash, int pid, ndrx_intmap_t **parents);
0384 
0385 extern NDRX_API int ndrx_proc_pid_get_from_ps(char *psout, pid_t *pid);
0386 extern NDRX_API int ndrx_proc_ppid_get_from_ps(char *psout, pid_t *ppid);
0387 
0388 extern NDRX_API void ndrx_proc_kill_list(string_list_t *list);
0389 extern NDRX_API int ndrx_proc_children_get_recursive(string_list_t **list, pid_t pid);
0390 extern NDRX_API int ndrx_proc_get_infos(pid_t pid, ndrx_proc_info_t *p_infos);
0391 extern NDRX_API int ndrx_sys_cmdout_test(char *fmt, pid_t pid, regex_t *p_re);
0392 extern NDRX_API void ndrx_sys_banner(void);
0393 extern NDRX_API int ndrx_atfork(void (*prepare)(void), void (*parent)(void),
0394        void (*child)(void));
0395 extern NDRX_API int ndrx_sys_sysv_user_res(ndrx_growlist_t *list, int queues);
0396 
0397 /* gen unix: */
0398 extern NDRX_API char * ndrx_sys_get_proc_name_by_ps(void);
0399 extern NDRX_API int ndrx_sys_is_process_running_by_kill(pid_t pid, char *proc_name);
0400 extern NDRX_API int ndrx_sys_is_process_running_by_ps(pid_t pid, char *proc_name);
0401 extern NDRX_API int ndrx_sys_is_process_running_by_pid(pid_t pid);
0402 
0403 
0404 /* sys_linux.c: */
0405 extern NDRX_API int ndrx_sys_is_process_running_procfs(pid_t pid, char *proc_name);
0406 
0407 /* sys_aix.c: */
0408 extern NDRX_API char * ndrx_sys_get_proc_name_getprocs(void);
0409 
0410 /* provided by: sys_<platform>.c */
0411 extern NDRX_API string_list_t* ndrx_sys_mqueue_list_make_pl(char *qpath, int *return_status);
0412 /* emulated message queue: */
0413 extern NDRX_API string_list_t* ndrx_sys_mqueue_list_make_emq(char *qpath, int *return_status);
0414 
0415 
0416 
0417 /** Test environmental variables of the PID 
0418  Sample regex: NDRX_SVCLOPT.{0,2}-k 0myWI5nu.*-i [0-9]+ --
0419  */
0420 extern NDRX_API int ndrx_sys_env_test(pid_t pid, regex_t *p_re);
0421 
0422 #if defined(EX_USE_SYSVQ) || defined(EX_USE_SVAPOLL)
0423 
0424 #define ndrx_sys_mqueue_list_make ndrx_sys_mqueue_list_make_svq
0425 
0426 #elif EX_USE_EMQ
0427 
0428 #define ndrx_sys_mqueue_list_make ndrx_sys_mqueue_list_make_emq
0429 
0430 #else
0431 
0432 #define ndrx_sys_mqueue_list_make ndrx_sys_mqueue_list_make_pl
0433 
0434 #endif
0435 
0436 
0437 #ifdef  __cplusplus
0438 }
0439 #endif
0440 
0441 #endif  /* SYS_UNIX_H */
0442 
0443 /* vim: set ts=4 sw=4 et smartindent: */