+ /* maximum limit of forked childs */
+ value = getenv("UDEVD_MAX_CHILDS");
+ if (value)
+ max_childs = strtoul(value, NULL, 10);
+ else {
+ int memsize = mem_size_mb();
+ if (memsize > 0)
+ max_childs = 128 + (memsize / 4);
+ else
+ max_childs = UDEVD_MAX_CHILDS;
+ }
+ info("initialize max_childs to %u", max_childs);
+
+ /* start to throttle forking if maximum number of _running_ childs is reached */
+ value = getenv("UDEVD_MAX_CHILDS_RUNNING");
+ if (value)
+ max_childs_running = strtoull(value, NULL, 10);
+ else {
+ int cpus = cpu_count();
+ if (cpus > 0)
+ max_childs_running = 8 + (8 * cpus);
+ else
+ max_childs_running = UDEVD_MAX_CHILDS_RUNNING;
+ }
+ info("initialize max_childs_running to %u", max_childs_running);
+
+ /* clear environment for forked event processes */
+ clearenv();
+
+ /* export log_priority , as called programs may want to follow that setting */
+ sprintf(udev_log, "UDEV_LOG=%i", udev_log_priority);
+ putenv(udev_log);
+
+ maxfd = udevd_sock;
+ maxfd = UDEV_MAX(maxfd, uevent_netlink_sock);
+ maxfd = UDEV_MAX(maxfd, signal_pipe[READ_END]);
+ maxfd = UDEV_MAX(maxfd, inotify_fd);
+
+ while (!udev_exit) {
+ struct udevd_uevent_msg *msg;
+ int fdcount;
+
+ FD_ZERO(&readfds);
+ FD_SET(signal_pipe[READ_END], &readfds);
+ FD_SET(udevd_sock, &readfds);
+ FD_SET(uevent_netlink_sock, &readfds);
+ if (inotify_fd >= 0)
+ FD_SET(inotify_fd, &readfds);
+
+ fdcount = select(maxfd+1, &readfds, NULL, NULL, NULL);
+ if (fdcount < 0) {
+ if (errno != EINTR)
+ err("error in select: %s", strerror(errno));
+ continue;
+ }
+
+ /* get control message */
+ if (FD_ISSET(udevd_sock, &readfds))
+ get_ctrl_msg();
+
+ /* get netlink message */
+ if (FD_ISSET(uevent_netlink_sock, &readfds)) {
+ msg = get_netlink_msg();
+ if (msg)
+ msg_queue_insert(msg);
+ }
+
+ /* received a signal, clear our notification pipe */
+ if (FD_ISSET(signal_pipe[READ_END], &readfds)) {
+ char buf[256];
+
+ read(signal_pipe[READ_END], &buf, sizeof(buf));
+ }
+
+ /* rules directory inotify watch */
+ if ((inotify_fd >= 0) && FD_ISSET(inotify_fd, &readfds)) {
+ int nbytes;
+
+ /* discard all possible events, we can just reload the config */
+ if ((ioctl(inotify_fd, FIONREAD, &nbytes) == 0) && nbytes) {
+ char *buf;
+
+ reload_config = 1;
+ buf = malloc(nbytes);
+ if (!buf) {
+ err("error getting buffer for inotify, disable watching");
+ close(inotify_fd);
+ inotify_fd = -1;
+ }
+ read(inotify_fd, buf, nbytes);
+ free(buf);
+ }
+ }
+
+ /* rules changed, set by inotify or a HUP signal */
+ if (reload_config) {
+ reload_config = 0;
+ udev_rules_cleanup(&rules);
+ udev_rules_init(&rules, 1);
+ }
+
+ /* forked child has returned */
+ if (sigchilds_waiting) {
+ sigchilds_waiting = 0;
+ reap_sigchilds();
+ }
+
+ if (run_exec_q) {
+ run_exec_q = 0;
+ if (!stop_exec_q)
+ msg_queue_manager();