Ejemplo n.º 1
0
bool XzeroDaemon::setup(std::unique_ptr<std::istream>&& settings, const std::string& filename, int optimizationLevel)
{
	TRACE(1, "setup(%s)", filename.c_str());

    FlowParser parser(this);
    parser.importHandler = std::bind(&XzeroDaemon::import, this, std::placeholders::_1, std::placeholders::_2,
            std::placeholders::_3);

    if (!parser.open(filename, std::move(settings))) {
        sd_notifyf(0, "ERRNO=%d", errno);
        fprintf(stderr, "Failed to open file: %s\n", filename.c_str());
        return false;
    }

	unit_ = parser.parse();
    if (!unit_)
        return false;

    if (dumpAST_)
        ASTPrinter::print(unit_.get());

    std::unique_ptr<IRProgram> ir = IRGenerator::generate(unit_.get());
    if (!ir) {
        fprintf(stderr, "IR generation failed. Aborting.\n");
        return false;
    }

    {
        PassManager pm;

        // mandatory passes
        pm.registerPass(std::make_unique<UnusedBlockPass>());

        // optional passes
        if (optimizationLevel >= 1) {
            pm.registerPass(std::make_unique<EmptyBlockElimination>());
            pm.registerPass(std::make_unique<InstructionElimination>());
        }

        pm.run(ir.get());
    }

    if (dumpIR_) {
        ir->dump();
    }

    program_ = TargetCodeGenerator().generate(ir.get());

    ir.reset();

    if (!program_) {
        fprintf(stderr, "Code generation failed. Aborting.\n");
        return false;
    }

    if (!program_->link(this)) {
        fprintf(stderr, "Program linking failed. Aborting.\n");
        return false;
    }

	if (!validateConfig()) {
		return false;
    }

    if (dumpTargetCode_)
        program_->dump();

	// run setup
	TRACE(1, "run 'setup'");
    if (program_->findHandler("setup")->run(nullptr))
        // should not return true
        return false;

	// grap the request handler
	TRACE(1, "get pointer to 'main'");

    {
        auto main = program_->findHandler("main");

        server_->requestHandler = [=](x0::HttpRequest* r) {
            FlowVM::Runner* cx = static_cast<FlowVM::Runner*>(r->setCustomData(r, main->createRunner()));
            cx->setUserData(r);
            bool handled = cx->run();
            if (!cx->isSuspended() && !handled) {
                r->finish();
            }
        };
    }

	// {{{ setup server-tag
	{
#if defined(HAVE_SYS_UTSNAME_H)
		{
			utsname utsname;
			if (uname(&utsname) == 0) {
				addComponent(std::string(utsname.sysname) + "/" + utsname.release);
				addComponent(utsname.machine);
			}
		}
#endif

#if defined(HAVE_BZLIB_H)
		{
			std::string zver("bzip2/");
			zver += BZ2_bzlibVersion();
			zver = zver.substr(0, zver.find(","));
			addComponent(zver);
		}
#endif

#if defined(HAVE_ZLIB_H)
		{
			std::string zver("zlib/");
			zver += zlib_version;
			addComponent(zver);
		}
#endif

		Buffer tagbuf;
		tagbuf.push_back("x0/" VERSION);

		if (!components_.empty())
		{
			tagbuf.push_back(" (");

			for (int i = 0, e = components_.size(); i != e; ++i)
			{
				if (i)
					tagbuf.push_back(", ");

				tagbuf.push_back(components_[i]);
			}

			tagbuf.push_back(")");
		}
		server_->tag = tagbuf.str();
	}
	// }}}

	// {{{ run post-config hooks
	TRACE(1, "setup: post_config");
	for (auto i: plugins_)
		if (!i->post_config())
			goto err;
	// }}}

	// {{{ run post-check hooks
	TRACE(1, "setup: post_check");
	for (auto i: plugins_)
		if (!i->post_check())
			goto err;
	// }}}

	// {{{ check for available TCP listeners
	if (server_->listeners().empty()) {
		log(Severity::error, "No HTTP listeners defined");
		goto err;
	}
	for (auto i: server_->listeners())
		if (!i->isOpen())
			goto err;
	// }}}

	// {{{ check for SO_REUSEPORT feature in TCP listeners
	if (server_->workers().size() == 1) {
		// fast-path scheduling for single-threaded mode
		server_->workers().front()->bind(server_->listeners().front());
	} else {
		std::list<ServerSocket*> dups;
		for (auto listener: server_->listeners()) {
			if (listener->reusePort()) {
				for (auto worker: server_->workers()) {
					if (worker->id() > 0) {
						// clone listener for non-main worker
						listener = listener->clone(worker->loop());
						dups.push_back(listener);
					}
					worker->bind(listener);
				}
			}
		}

		// FIXME: this is not yet well thought.
		// - how to handle configuration file reloads wrt SO_REUSEPORT?
		for (auto dup: dups) {
			server_->listeners().push_back(dup);
		}
	}
	// }}}

	// {{{ x0d: check for superfluous passed file descriptors (and close them)
	for (auto fd: ServerSocket::getInheritedSocketList()) {
		bool found = false;
		for (auto li: server_->listeners()) {
			if (fd == li->handle()) {
				found = true;
				break;
			}
		}
		if (!found) {
			log(Severity::debug, "Closing inherited superfluous listening socket %d.", fd);
			::close(fd);
		}
	}
	// }}}

	// {{{ systemd: check for superfluous passed file descriptors
	if (int count = sd_listen_fds(0)) {
		int maxfd = SD_LISTEN_FDS_START + count;
		count = 0;
		for (int fd = SD_LISTEN_FDS_START; fd < maxfd; ++fd) {
			bool found = false;
			for (auto li: server_->listeners()) {
				if (fd == li->handle()) {
					found = true;
					break;
				}
			}
			if (!found) {
				++count;
			}
		}
		if (count) {
			fprintf(stderr, "superfluous systemd file descriptors: %d\n", count);
			return false;
		}
	}
	// }}}

	// XXX post worker wakeup
	// we do an explicit wakeup of all workers here since there might be already
	// some (configure-time related) events pending, i.e. director's (fcgi) health checker
	// FIXME this is more a workaround than a fix.
	for (auto worker: server_->workers())
		worker->wakeup();

	TRACE(1, "setup: done.");
	return true;

err:
	return false;
}
Ejemplo n.º 2
0
    EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
    {
        EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, "
              "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list);

        try
        {
            // Get the requested client version (default is 1) and check it is 2 or 3.
            EGLint client_version = 1;
            bool reset_notification = false;
            bool robust_access = false;

            if (attrib_list)
            {
                for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
                {
                    switch (attribute[0])
                    {
                    case EGL_CONTEXT_CLIENT_VERSION:
                        client_version = attribute[1];
                        break;
                    case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
                        if (attribute[1] == EGL_TRUE)
                        {
                            return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);   // Unimplemented
                            // robust_access = true;
                        }
                        else if (attribute[1] != EGL_FALSE)
                            return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
                        break;
                    case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
                        if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT)
                            reset_notification = true;
                        else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT)
                            return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
                        break;
                    default:
                        return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
                    }
                }
            }

            if (client_version != 2 && client_version != 3)
            {
                return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
            }

            egl::Display *display = static_cast<egl::Display*>(dpy);

            if (share_context)
            {
                gl::Context* sharedGLContext = static_cast<gl::Context*>(share_context);

                if (sharedGLContext->isResetNotificationEnabled() != reset_notification)
                {
                    return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
                }

                if (sharedGLContext->getClientVersion() != client_version)
                {
                    return egl::error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
                }

                // Can not share contexts between displays
                if (sharedGLContext->getRenderer() != display->getRenderer())
                {
                    return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
                }
            }

            if (!validateConfig(display, config))
            {
                return EGL_NO_CONTEXT;
            }

            return display->createContext(config, client_version, static_cast<gl::Context*>(share_context), reset_notification, robust_access);
        }
        catch (...)
        {
            return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
        }
    }