Exemple #1
0
void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {

    int i, ret;

    char spool_buf[0xffff];
    struct uwsgi_header uh;
    char *body = NULL;
    size_t body_len = 0;

    int spool_fd;

    if (!dir) dir = uspool->dir;

    if (!strncmp("uwsgi_spoolfile_on_", task, 19) || (uwsgi.spooler_ordered && is_a_number(task))) {
        struct stat sf_lstat;
        if (lstat(task, &sf_lstat)) {
            return;
        }

        // a spool request for the future
        if (sf_lstat.st_mtime > uwsgi_now()) {
            return;
        }

#ifdef __linux__
        if (S_ISDIR(sf_lstat.st_mode) && uwsgi.spooler_ordered) {
            if (chdir(task)) {
                uwsgi_error("chdir()");
                return;
            }
            char *prio_path = realpath(".", NULL);
            spooler_scandir(uspool, prio_path);
            free(prio_path);
            if (chdir(dir)) {
                uwsgi_error("chdir()");
            }
            return;
        }
#endif
        if (!S_ISREG(sf_lstat.st_mode)) {
            return;
        }
        if (!access(task, R_OK | W_OK)) {

            spool_fd = open(task, O_RDWR);

            if (spool_fd < 0) {
                if (errno != ENOENT)
                    uwsgi_error_open(task);
                return;
            }

            // check if the file is locked by another process
            if (uwsgi_fcntl_is_locked(spool_fd)) {
                uwsgi_protected_close(spool_fd);
                return;
            }

            // unlink() can destroy the lock !!!
            if (access(task, R_OK | W_OK)) {
                uwsgi_protected_close(spool_fd);
                return;
            }

            ssize_t rlen = uwsgi_protected_read(spool_fd, &uh, 4);

            if (rlen != 4) {
                // it could be here for broken file or just opened one
                if (rlen < 0)
                    uwsgi_error("read()");
                uwsgi_protected_close(spool_fd);
                return;
            }

#ifdef __BIG_ENDIAN__
            uh.pktsize = uwsgi_swap16(uh.pktsize);
#endif

            if (uwsgi_protected_read(spool_fd, spool_buf, uh.pktsize) != uh.pktsize) {
                uwsgi_error("read()");
                destroy_spool(dir, task);
                uwsgi_protected_close(spool_fd);
                return;
            }

            // body available ?
            if (sf_lstat.st_size > (uh.pktsize+4)) {
                body_len = sf_lstat.st_size - (uh.pktsize+4);
                body = uwsgi_malloc(body_len);
                if ((size_t)uwsgi_protected_read(spool_fd, body, body_len) != body_len) {
                    uwsgi_error("read()");
                    destroy_spool(dir, task);
                    uwsgi_protected_close(spool_fd);
                    free(body);
                    return;
                }
            }

            // now the task is running and should not be waken up
            uspool->running = 1;

            if (!uwsgi.spooler_quiet)
                uwsgi_log("[spooler %s pid: %d] managing request %s ...\n", uspool->dir, (int) uwsgi.mypid, task);


            // chdir before running the task (if requested)
            if (uwsgi.spooler_chdir) {
                if (chdir(uwsgi.spooler_chdir)) {
                    uwsgi_error("chdir()");
                }
            }

            int callable_found = 0;
            for(i=0; i<256; i++) {
                if (uwsgi.p[i]->spooler) {
                    time_t now = uwsgi_now();
                    if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
                        set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
                    }
                    ret = uwsgi.p[i]->spooler(task, spool_buf, uh.pktsize, body, body_len);
                    if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
                        set_spooler_harakiri(0);
                    }
                    if (ret == 0) continue;
                    callable_found = 1;
                    // increase task counter
                    uspool->tasks++;
                    if (ret == -2) {
                        if (!uwsgi.spooler_quiet)
                            uwsgi_log("[spooler %s pid: %d] done with task %s after %d seconds\n", uspool->dir, (int) uwsgi.mypid, task, uwsgi_now()-now);
                        destroy_spool(dir, task);
                    }
                    // re-spool it
                    break;
                }
            }

            if (body)
                free(body);

            // here we free and unlock the task
            uwsgi_protected_close(spool_fd);
            uspool->running = 0;

            if (chdir(dir)) {
                uwsgi_error("chdir()");
                uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
                exit(1);
            }

            if (!callable_found) {
                uwsgi_log("unable to find the spooler function, have you loaded it into the spooler process ?\n");
            }

        }
    }
}
Exemple #2
0
int uwsgi_signal_handler(uint8_t sig) {

	struct uwsgi_signal_entry *use = NULL;

	use = &uwsgi.shared->signal_table[sig];

	if (!uwsgi.p[use->modifier1]->signal_handler) {
		return -1;
	}

	// check for COW
	if (uwsgi.master_process) {
		if (use->wid != 0 && use->wid != uwsgi.mywid) {
			uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid);
			return -1;
		}
	}
	// in lazy mode (without a master), only the same worker will be able to run handlers
	else if (uwsgi.lazy) {
		if (use->wid != uwsgi.mywid) {
			uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid);
			return -1;
		}
	}
	else {
		// when master is not active, worker1 is the COW-leader
		if (use->wid != 1 && use->wid != uwsgi.mywid) {
			uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid);
			return -1;
		}
	}

	// set harakiri here (if required and if i am a worker)

	if (uwsgi.mywid > 0) {
		uwsgi.workers[uwsgi.mywid].sig = 1;
		uwsgi.workers[uwsgi.mywid].signum = sig;
		uwsgi.workers[uwsgi.mywid].signals++;
		if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
			set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
		}
	}
	else if (uwsgi.muleid > 0) {
		uwsgi.mules[uwsgi.muleid - 1].sig = 1;
		uwsgi.mules[uwsgi.muleid - 1].signum = sig;
		uwsgi.mules[uwsgi.muleid - 1].signals++;
		if (uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI] > 0) {
			set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
		}
	}
#ifdef UWSGI_SPOOLER
	else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
		if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
			set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
		}
	}
#endif

	int ret = uwsgi.p[use->modifier1]->signal_handler(sig, use->handler);

	if (uwsgi.mywid > 0) {
		uwsgi.workers[uwsgi.mywid].sig = 0;
		if (uwsgi.workers[uwsgi.mywid].harakiri > 0) {
			set_harakiri(0);
		}
	}
	else if (uwsgi.muleid > 0) {
		uwsgi.mules[uwsgi.muleid - 1].sig = 0;
		if (uwsgi.mules[uwsgi.muleid - 1].harakiri > 0) {
			set_mule_harakiri(0);
		}
	}
#ifdef UWSGI_SPOOLER
	else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
		if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
			set_spooler_harakiri(0);
		}
	}
#endif

	return ret;
}
Exemple #3
0
void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {

	int i, ret;

	char spool_buf[0xffff];
	struct uwsgi_header uh;
	char *body = NULL;
	size_t body_len = 0;

	int spool_fd;

	if (!dir)
		dir = uspool->dir;

	if (!strncmp("uwsgi_spoolfile_on_", task, 19) || (uwsgi.spooler_ordered && is_a_number(task))) {
		struct stat sf_lstat;

		if (lstat(task, &sf_lstat)) {
			return;
		}

		// a spool request for the future
		if (sf_lstat.st_mtime > uwsgi_now()) {
			return;
		}

		if (S_ISDIR(sf_lstat.st_mode) && uwsgi.spooler_ordered) {
			if (chdir(task)) {
				uwsgi_error("spooler_manage_task()/chdir()");
				return;
			}
#ifdef __UCLIBC__ 
			char *prio_path = uwsgi_malloc(PATH_MAX);
			realpath(".", prio_path);		
#else 
			char *prio_path = realpath(".", NULL);
#endif
			spooler_scandir(uspool, prio_path);
			free(prio_path);
			if (chdir(dir)) {
				uwsgi_error("spooler_manage_task()/chdir()");
			}
			return;
		}
		if (!S_ISREG(sf_lstat.st_mode)) {
			return;
		}
		if (!access(task, R_OK | W_OK)) {

			spool_fd = open(task, O_RDWR);

			if (spool_fd < 0) {
				if (errno != ENOENT)
					uwsgi_error_open(task);
				return;
			}

			if (uwsgi_spooler_read_header(task, spool_fd, &uh))
				return;

			// access lstat second time after getting a lock
			// first-time lstat could be dirty (for example between writes in master)
			if (lstat(task, &sf_lstat)) {
				return;
			}

			if (uwsgi_spooler_read_content(spool_fd, spool_buf, &body, &body_len, &uh, &sf_lstat)) {
				destroy_spool(dir, task);
				return;
			}

			// now the task is running and should not be woken up
			uspool->running = 1;
			// this is used in cheap mode for making decision about who must die
			uspool->last_task_managed = uwsgi_now();

			if (!uwsgi.spooler_quiet)
				uwsgi_log("[spooler %s pid: %d] managing request %s ...\n", uspool->dir, (int) uwsgi.mypid, task);


			// chdir before running the task (if requested)
			if (uwsgi.spooler_chdir) {
				if (chdir(uwsgi.spooler_chdir)) {
					uwsgi_error("spooler_manage_task()/chdir()");
				}
			}

			int callable_found = 0;
			for (i = 0; i < 256; i++) {
				if (uwsgi.p[i]->spooler) {
					time_t now = uwsgi_now();
					if (uwsgi.harakiri_options.spoolers > 0) {
						set_spooler_harakiri(uwsgi.harakiri_options.spoolers);
					}
					ret = uwsgi.p[i]->spooler(task, spool_buf, uh._pktsize, body, body_len);
					if (uwsgi.harakiri_options.spoolers > 0) {
						set_spooler_harakiri(0);
					}
					if (ret == 0)
						continue;
					callable_found = 1;
					// increase task counter
					uspool->tasks++;
					if (ret == -2) {
						if (!uwsgi.spooler_quiet)
							uwsgi_log("[spooler %s pid: %d] done with task %s after %lld seconds\n", uspool->dir, (int) uwsgi.mypid, task, (long long) uwsgi_now() - now);
						destroy_spool(dir, task);
					}
					// re-spool it
					break;
				}
			}

			if (body)
				free(body);

			// here we free and unlock the task
			uwsgi_protected_close(spool_fd);
			uspool->running = 0;


			// need to recycle ?
			if (uwsgi.spooler_max_tasks > 0 && uspool->tasks >= (uint64_t) uwsgi.spooler_max_tasks) {
				uwsgi_log("[spooler %s pid: %d] maximum number of tasks reached (%d) recycling ...\n", uspool->dir, (int) uwsgi.mypid, uwsgi.spooler_max_tasks);
				end_me(0);
			}


			if (chdir(dir)) {
				uwsgi_error("chdir()");
				uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
				exit(1);
			}

			if (!callable_found) {
				uwsgi_log("unable to find the spooler function, have you loaded it into the spooler process ?\n");
			}

		}
	}
}