예제 #1
0
파일: coroae.c 프로젝트: Perkville/uwsgi
static SV *coroae_add_signal_watcher(const char *signame, CV *cb) {

	SV *newobj;

	dSP;

	ENTER;
	SAVETMPS;
	PUSHMARK(SP);
	mXPUSHs(newSVpvs("AnyEvent"));
	mXPUSHs(newSVpvs("signal"));
	mXPUSHs(newSVpv(signame, 0));
	mXPUSHs(newSVpvs("cb"));
	mXPUSHs(newRV_noinc((SV *)cb));
	PUTBACK;

	call_method("signal", G_SCALAR|G_EVAL);

	SPAGAIN;
	if(SvTRUE(ERRSV)) {
		// no need to continue...
		uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
		exit(1);
	}
	else {
		newobj = SvREFCNT_inc(POPs);
	}
	PUTBACK;
	FREETMPS;
	LEAVE;

	return newobj;

}
예제 #2
0
MAGIC *find_shadow_magic(SV *p6cb, SV *static_class, SV *obj) {
    SV * const obj_deref = SvRV(obj);
    MAGIC * mg = mg_find(obj_deref, '~');
    if (mg == NULL || ((_perl6_magic*)(mg->mg_ptr))->key != PERL6_EXTENSION_MAGIC_KEY) {
        /* need to create the shadow object here */

        AV * method_args = newAV();
        SV * method_args_rv = newRV_noinc((SV *) method_args);
        av_extend(method_args, 1);
        SvREFCNT_inc(obj);
        av_store(method_args, 0, obj);

        AV * args = newAV();
        av_extend(args, 3);
        SvREFCNT_inc(static_class);
        av_store(args, 0, static_class);
        av_store(args, 1, newSVpvs("new_shadow_of_p5_object"));
        av_store(args, 2, method_args_rv);

        MAGIC * const p6cb_mg = mg_find(SvRV(p6cb), '~');
        _perl6_magic* const p6cb_p6mg = (_perl6_magic*)(p6cb_mg->mg_ptr);
        SV *err = NULL;
        SV * const args_rv = newRV_noinc((SV *) args);

        declare_cbs;
        cbs->call_p6_method(p6cb_p6mg->index, "invoke", 1, args_rv, &err);
        SvREFCNT_dec(args_rv);
        handle_p6_error(err);

        mg = mg_find(obj_deref, '~');
    }
    return mg;
}
예제 #3
0
파일: coroae.c 프로젝트: Perkville/uwsgi
// create a new coro
SV * coroae_coro_new(CV *block) {
	SV *newobj = NULL;
	dSP;
        ENTER;
        SAVETMPS;
        PUSHMARK(SP);
        mXPUSHs(newSVpvs("Coro"));
        mXPUSHs(newRV_noinc((SV *)block));
        PUTBACK;
        call_method("new", G_SCALAR|G_EVAL);
        SPAGAIN;
        if(SvTRUE(ERRSV)) {
                uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
                (void)POPs; // we must pop undef from the stack in G_SCALAR context
        }
        else {
                newobj = SvREFCNT_inc(POPs);
        }
	PUTBACK;
        FREETMPS;
        LEAVE;
	return newobj;
}
예제 #4
0
void _parse_header(pTHX_ srl_splitter_t *splitter) {
    int magic_string = 1;
    int high_magic_string = 1;

    U8 version_encoding;
    U8 version;
    U8 encoding_flags;
    UV header_len;

    int is_zlib_encoded = 0;
    int is_snappy_encoded = 0;
    int is_snappyincr_encoded = 0;

    // SRL_MAGIC_STRLEN + PROTOCOL_LENGTH + OPTIONAL-HEADER-SIZE(at least 1 byte) + DATA(at least 1 byte)
    if (splitter->input_len < SRL_MAGIC_STRLEN + 1 + 1 + 1){
        croak("input Sereal string lacks data");
    } else if ( (high_magic_string = strncmp(splitter->input_str, SRL_MAGIC_STRING, SRL_MAGIC_STRLEN))
                  && (magic_string = strncmp(splitter->input_str, SRL_MAGIC_STRING_HIGHBIT, SRL_MAGIC_STRLEN)) ) {
        croak("input Sereal string has wrong Sereal magic");
    }

    splitter->pos += SRL_MAGIC_STRLEN;

    version_encoding = (U8)*(splitter->pos);
    version = (U8)(version_encoding & SRL_PROTOCOL_VERSION_MASK);
    encoding_flags = (U8)(version_encoding & SRL_PROTOCOL_ENCODING_MASK);

    if (      version <= 0
              || ( version < 3 && high_magic_string )
              || ( version > 2 && magic_string ) ) {
        croak("unsupported Sereal versions/protocol");
    }

    switch(encoding_flags) {

   case SRL_PROTOCOL_ENCODING_RAW:
        /* no op */
        SRL_SPLITTER_TRACE("encoding is raw %s", "");
        break;

    case SRL_PROTOCOL_ENCODING_SNAPPY:
        SRL_SPLITTER_TRACE("encoding is snappy %s", "");
        is_snappy_encoded = 1;
        break;

    case SRL_PROTOCOL_ENCODING_SNAPPY_INCREMENTAL:
        SRL_SPLITTER_TRACE("encoding is snappy incr %s", "");
        is_snappy_encoded = is_snappyincr_encoded = 1;
        break;

    case SRL_PROTOCOL_ENCODING_ZLIB:
        SRL_SPLITTER_TRACE("encoding is zlib %s", "");
        is_zlib_encoded = 1;
        break;

    default:
        croak("Sereal document encoded in an unknown format");
    }

    SRL_SPLITTER_TRACE("header version is %hhu", version);

    // move after protocol version
    splitter->pos += 1;
    
    header_len= _read_varint_uv_nocheck(splitter);

    SRL_SPLITTER_TRACE("header len is %lu", header_len);

    //TODO: add code for processing the header
    splitter->pos += header_len;

    if (version < 2) {
        splitter->input_body_pos = splitter->input_str;
    } else {
        splitter->input_body_pos = splitter->pos;
    }

    if (is_snappy_encoded) {
        UV compressed_len;
        uint32_t uncompressed_len;
        int decompress_ok;
        char * new_input_str;

        if (is_snappyincr_encoded) {
            compressed_len = _read_varint_uv_nocheck(splitter);
        } else {
            compressed_len = splitter->input_len - (splitter->pos - splitter->input_str);
        }
        SRL_SPLITTER_TRACE("snappy compressed len %"UVuf, compressed_len);
        // splitter->pos is now at start of compressed payload

        int snappy_header_len;
        char *old_pos;
        old_pos = splitter->pos;
        snappy_header_len = csnappy_get_uncompressed_length(
            (char *)old_pos,
            compressed_len,
            &uncompressed_len
        );
        if (snappy_header_len == CSNAPPY_E_HEADER_BAD) {
            croak("invalid Snappy header in Snappy-compressed Sereal packet");
        }

        // allocate a new SV for uncompressed data
        SvREFCNT_dec(splitter->input_sv);
        splitter->input_sv = newSVpvs("");
        new_input_str = SvGROW(splitter->input_sv, uncompressed_len);

        decompress_ok = csnappy_decompress_noheader((char *) (old_pos + snappy_header_len),
                                                    compressed_len - snappy_header_len,
                                                    (char *) new_input_str,
                                                    &uncompressed_len);
        if ( decompress_ok != 0 ) {
            croak("Snappy decompression of Sereal packet payload failed");
        }

        splitter->input_str = new_input_str;
        SRL_SPLITTER_TRACE(" decompress OK: uncompressed length: %d\n", uncompressed_len);

        splitter->pos = splitter->input_str;;
        splitter->input_len = uncompressed_len;
        splitter->input_body_pos = splitter->pos;

    } else if (is_zlib_encoded) {

        UV uncompressed_len = _read_varint_uv_nocheck(splitter);
        UV compressed_len = _read_varint_uv_nocheck(splitter);
        char * new_input_str;

        // splitter->pos is now at start of compressed payload
        SRL_SPLITTER_TRACE("unzipping %s", "");
        SRL_SPLITTER_TRACE("compressed_len : %" UVuf, compressed_len);
        SRL_SPLITTER_TRACE("uncompressed_len : %" UVuf, uncompressed_len);

                 
        mz_ulong tmp = uncompressed_len;

        // allocate a new SV for uncompressed data
        SvREFCNT_dec(splitter->input_sv);
        splitter->input_sv = newSVpvs("");
        new_input_str = SvGROW(splitter->input_sv, uncompressed_len);

        char *compressed = splitter->pos;

        int decompress_ok = mz_uncompress( (unsigned char *) new_input_str,
                                           &tmp,
                                           (const unsigned char *) compressed,
                                           compressed_len );

        if (decompress_ok != Z_OK)
            croak("ZLIB decompression of Sereal packet payload failed");

        splitter->input_str = new_input_str;
        SRL_SPLITTER_TRACE(" decompress OK: length %lu\n", uncompressed_len);

        splitter->pos = splitter->input_str;
        splitter->input_len = (STRLEN)tmp;
        splitter->input_body_pos = splitter->pos;

    }
}
예제 #5
0
/*
=for apidoc mro_package_moved

Call this function to signal to a stash that it has been assigned to
another spot in the stash hierarchy.  C<stash> is the stash that has been
assigned.  C<oldstash> is the stash it replaces, if any.  C<gv> is the glob
that is actually being assigned to.

This can also be called with a null first argument to
indicate that C<oldstash> has been deleted.

This function invalidates isa caches on the old stash, on all subpackages
nested inside it, and on the subclasses of all those, including
non-existent packages that have corresponding entries in C<stash>.

It also sets the effective names (C<HvENAME>) on all the stashes as
appropriate.

If the C<gv> is present and is not in the symbol table, then this function
simply returns.  This checked will be skipped if C<flags & 1>.

=cut
*/
void
Perl_mro_package_moved(pTHX_ HV * const stash, HV * const oldstash,
                       const GV * const gv, U32 flags)
{
    SV *namesv;
    HEK **namep;
    I32 name_count;
    HV *stashes;
    HE* iter;

    PERL_ARGS_ASSERT_MRO_PACKAGE_MOVED;
    assert(stash || oldstash);

    /* Determine the name(s) of the location that stash was assigned to
     * or from which oldstash was removed.
     *
     * We cannot reliably use the name in oldstash, because it may have
     * been deleted from the location in the symbol table that its name
     * suggests, as in this case:
     *
     *   $globref = \*foo::bar::;
     *   Symbol::delete_package("foo");
     *   *$globref = \%baz::;
     *   *$globref = *frelp::;
     *      # calls mro_package_moved(%frelp::, %baz::, *$globref, NULL, 0)
     *
     * So we get it from the gv. But, since the gv may no longer be in the
     * symbol table, we check that first. The only reliable way to tell is
     * to see whether its stash has an effective name and whether the gv
     * resides in that stash under its name. That effective name may be
     * different from what gv_fullname4 would use.
     * If flags & 1, the caller has asked us to skip the check.
     */
    if(!(flags & 1)) {
        SV **svp;
        if(
            !GvSTASH(gv) || !HvENAME(GvSTASH(gv)) ||
            !(svp = hv_fetchhek(GvSTASH(gv), GvNAME_HEK(gv), 0)) ||
            *svp != (SV *)gv
        ) return;
    }
    assert(SvOOK(GvSTASH(gv)));
    assert(GvNAMELEN(gv));
    assert(GvNAME(gv)[GvNAMELEN(gv) - 1] == ':');
    assert(GvNAMELEN(gv) == 1 || GvNAME(gv)[GvNAMELEN(gv) - 2] == ':');
    name_count = HvAUX(GvSTASH(gv))->xhv_name_count;
    if (!name_count) {
        name_count = 1;
        namep = &HvAUX(GvSTASH(gv))->xhv_name_u.xhvnameu_name;
    }
    else {
        namep = HvAUX(GvSTASH(gv))->xhv_name_u.xhvnameu_names;
        if (name_count < 0) ++namep, name_count = -name_count - 1;
    }
    if (name_count == 1) {
        if (HEK_LEN(*namep) == 4 && strnEQ(HEK_KEY(*namep), "main", 4)) {
            namesv = GvNAMELEN(gv) == 1
                     ? newSVpvs_flags(":", SVs_TEMP)
                     : newSVpvs_flags("",  SVs_TEMP);
        }
        else {
            namesv = sv_2mortal(newSVhek(*namep));
            if (GvNAMELEN(gv) == 1) sv_catpvs(namesv, ":");
            else                    sv_catpvs(namesv, "::");
        }
        if (GvNAMELEN(gv) != 1) {
            sv_catpvn_flags(
                namesv, GvNAME(gv), GvNAMELEN(gv) - 2,
                /* skip trailing :: */
                GvNAMEUTF8(gv) ? SV_CATUTF8 : SV_CATBYTES
            );
        }
    }
    else {
        SV *aname;
        namesv = sv_2mortal((SV *)newAV());
        while (name_count--) {
            if(HEK_LEN(*namep) == 4 && strnEQ(HEK_KEY(*namep), "main", 4)) {
                aname = GvNAMELEN(gv) == 1
                        ? newSVpvs(":")
                        : newSVpvs("");
                namep++;
            }
            else {
                aname = newSVhek(*namep++);
                if (GvNAMELEN(gv) == 1) sv_catpvs(aname, ":");
                else                    sv_catpvs(aname, "::");
            }
            if (GvNAMELEN(gv) != 1) {
                sv_catpvn_flags(
                    aname, GvNAME(gv), GvNAMELEN(gv) - 2,
                    /* skip trailing :: */
                    GvNAMEUTF8(gv) ? SV_CATUTF8 : SV_CATBYTES
                );
            }
            av_push((AV *)namesv, aname);
        }
    }

    /* Get a list of all the affected classes. */
    /* We cannot simply pass them all to mro_isa_changed_in to avoid
       the list, as that function assumes that only one package has
       changed. It does not work with:

          @foo::ISA = qw( B B::B );
          *B:: = delete $::{"A::"};

       as neither B nor B::B can be updated before the other, since they
       will reset caches on foo, which will see either B or B::B with the
       wrong name. The names must be set on *all* affected stashes before
       we do anything else. (And linearisations must be cleared, too.)
     */
    stashes = (HV *) sv_2mortal((SV *)newHV());
    mro_gather_and_rename(
        stashes, (HV *) sv_2mortal((SV *)newHV()),
        stash, oldstash, namesv
    );

    /* Once the caches have been wiped on all the classes, call
       mro_isa_changed_in on each. */
    hv_iterinit(stashes);
    while((iter = hv_iternext(stashes))) {
        HV * const stash = *(HV **)HEK_KEY(HeKEY_hek(iter));
        if(HvENAME(stash)) {
            /* We have to restore the original meta->isa (that
               mro_gather_and_rename set aside for us) this way, in case
               one class in this list is a superclass of a another class
               that we have already encountered. In such a case, meta->isa

               from PL_isarev. */
            struct mro_meta * const meta = HvMROMETA(stash);
            if(meta->isa != (HV *)HeVAL(iter)) {
                SvREFCNT_dec(meta->isa);
                meta->isa
                    = HeVAL(iter) == &PL_sv_yes
                      ? NULL
                      : (HV *)HeVAL(iter);
                HeVAL(iter) = NULL; /* We donated our reference count. */
            }
            mro_isa_changed_in(stash);
        }
    }
}
예제 #6
0
void
my_xsinit(pTHX)
{
    dVAR;
    static const char file[] = __FILE__;

#ifdef USE_CTRLX
    GV *ctrlXgv;
    SV *ctrlX;
#endif

#ifdef USE_SUBFILE
    if (PL_preprocess)
        croak("Can't use -P with pl2exe");
#endif

#ifdef NEED_INIT_WIN32CORE
    init_Win32CORE(aTHX);
#endif

#ifdef USE_ZIP
    pl2exe_boot_zip(aTHX);
#endif

#ifdef NEED_PREAMBLE
    newXS("ExtUtils::PerlToExe::preamble",
        XS_ExtUtils_PerlToExe_preamble,
        file);

    if (!PL_preambleav)
        PL_preambleav = newAV();
    av_push(PL_preambleav, 
        newSVpvs("BEGIN { ExtUtils::PerlToExe::preamble() }"));
#endif

#ifdef NEED_TAINT
    TAINT;
    TAINT_PROPER("appended " TAINT_TYPE);
    TAINT_NOT;
#endif

#ifdef USE_CTRLX
    ctrlXgv = gv_fetchpvs("\030", GV_NOTQUAL, SVt_PV);
    ctrlX   = GvSV(ctrlXgv);

    /*
     * We can't reopen PL_rsfp yet as it hasn't been set (the file is
     * open, it's just in an auto variable in S_parse_body). However,
     * it's easier to fixup the name here, before gv_fetch_file gets
     * called on it.
     */

    PL_origfilename = savepv(SvPV_nolen(ctrlX));
    CopFILE_free(PL_curcop);
    CopFILE_set(PL_curcop, PL_origfilename);

    sv_setpv(ctrlX, CTRL_X);
    SvTAINTED_on(ctrlX);
#endif

#ifdef USE_ZIP
    pl2exe_load_zip(aTHX_ PL_origfilename);
#endif

    real_xsinit(aTHX);
}