Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/Mac/Tools/pythonw.c

    r2 r391  
    44 * GUI code: some GUI API's don't work unless the program is inside an
    55 * application bundle.
     6 *
     7 * This program uses posix_spawn rather than plain execv because we need
     8 * slightly more control over how the "real" interpreter is executed.
     9 *
     10 * On OSX 10.4 (and earlier) this falls back to using exec because the
     11 * posix_spawnv functions aren't available there.
    612 */
     13#pragma weak_import posix_spawnattr_init
     14#pragma weak_import posix_spawnattr_setbinpref_np
     15#pragma weak_import posix_spawnattr_setflags
     16#pragma weak_import posix_spawn
     17
     18#include <Python.h>
    719#include <unistd.h>
     20#ifdef HAVE_SPAWN_H
     21#include <spawn.h>
     22#endif
     23#include <stdio.h>
     24#include <string.h>
     25#include <errno.h>
    826#include <err.h>
     27#include <dlfcn.h>
     28#include <stdlib.h>
    929
    10 static char Python[] = PYTHONWEXECUTABLE;
    1130
    12 int main(int argc, char **argv) {
    13         argv[0] = Python;
    14         execv(Python, argv);
    15         err(1, "execv: %s", Python);
    16         /* NOTREACHED */
     31extern char** environ;
     32
     33/*
     34 * Locate the python framework by looking for the
     35 * library that contains Py_Initialize.
     36 *
     37 * In a regular framework the structure is:
     38 *
     39 *    Python.framework/Versions/2.7
     40 *              /Python
     41 *              /Resources/Python.app/Contents/MacOS/Python
     42 *
     43 * In a virtualenv style structure the expected
     44 * structure is:
     45 *
     46 *    ROOT
     47 *       /bin/pythonw
     48 *       /.Python   <- the dylib
     49 *       /.Resources/Python.app/Contents/MacOS/Python
     50 *
     51 * NOTE: virtualenv's are not an officially supported
     52 * feature, support for that structure is provided as
     53 * a convenience.
     54 */
     55static char* get_python_path(void)
     56{
     57    size_t len;
     58    Dl_info info;
     59    char* end;
     60    char* g_path;
     61
     62    if (dladdr(Py_Initialize, &info) == 0) {
     63        return NULL;
     64    }
     65
     66    len = strlen(info.dli_fname);
     67
     68    g_path = malloc(len+60);
     69    if (g_path == NULL) {
     70        return NULL;
     71    }
     72
     73    strcpy(g_path, info.dli_fname);
     74    end = g_path + len - 1;
     75    while (end != g_path && *end != '/') {
     76        end --;
     77    }
     78    end++;
     79    if (*end == '.') {
     80        end++;
     81    }
     82    strcpy(end, "Resources/Python.app/Contents/MacOS/" PYTHONFRAMEWORK);
     83
     84    return g_path;
    1785}
     86
     87#ifdef HAVE_SPAWN_H
     88static void
     89setup_spawnattr(posix_spawnattr_t* spawnattr)
     90{
     91    size_t ocount;
     92    size_t count;
     93    cpu_type_t cpu_types[1];
     94    short flags = 0;
     95#ifdef __LP64__
     96    int   ch;
     97#endif
     98
     99    if ((errno = posix_spawnattr_init(spawnattr)) != 0) {
     100        err(2, "posix_spawnattr_int");
     101        /* NOTREACHTED */
     102    }
     103
     104    count = 1;
     105
     106    /* Run the real python executable using the same architecture as this
     107     * executable, this allows users to control the architecture using
     108     * "arch -ppc python"
     109     */
     110
     111#if defined(__ppc64__)
     112    cpu_types[0] = CPU_TYPE_POWERPC64;
     113
     114#elif defined(__x86_64__)
     115    cpu_types[0] = CPU_TYPE_X86_64;
     116
     117#elif defined(__ppc__)
     118    cpu_types[0] = CPU_TYPE_POWERPC;
     119#elif defined(__i386__)
     120    cpu_types[0] = CPU_TYPE_X86;
     121#else
     122#       error "Unknown CPU"
     123#endif
     124
     125    if (posix_spawnattr_setbinpref_np(spawnattr, count,
     126                            cpu_types, &ocount) == -1) {
     127        err(1, "posix_spawnattr_setbinpref");
     128        /* NOTREACHTED */
     129    }
     130    if (count != ocount) {
     131        fprintf(stderr, "posix_spawnattr_setbinpref failed to copy\n");
     132        exit(1);
     133        /* NOTREACHTED */
     134    }
     135
     136
     137    /*
     138     * Set flag that causes posix_spawn to behave like execv
     139     */
     140    flags |= POSIX_SPAWN_SETEXEC;
     141    if ((errno = posix_spawnattr_setflags(spawnattr, flags)) != 0) {
     142        err(1, "posix_spawnattr_setflags");
     143        /* NOTREACHTED */
     144    }
     145}
     146#endif
     147
     148int
     149main(int argc, char **argv) {
     150    char* exec_path = get_python_path();
     151
     152    /*
     153     * Let argv[0] refer to the new interpreter. This is needed to
     154     * get the effect we want on OSX 10.5 or earlier. That is, without
     155     * changing argv[0] the real interpreter won't have access to
     156     * the Window Server.
     157     */
     158    argv[0] = exec_path;
     159
     160#ifdef HAVE_SPAWN_H
     161
     162    /* We're weak-linking to posix-spawnv to ensure that
     163     * an executable build on 10.5 can work on 10.4.
     164     */
     165    if (posix_spawn != NULL) {
     166        posix_spawnattr_t spawnattr = NULL;
     167
     168
     169        setup_spawnattr(&spawnattr);
     170        posix_spawn(NULL, exec_path, NULL,
     171            &spawnattr, argv, environ);
     172        err(1, "posix_spawn: %s", exec_path);
     173    }
     174#endif
     175    execve(exec_path, argv, environ);
     176    err(1, "execve: %s", argv[0]);
     177    /* NOTREACHED */
     178}
Note: See TracChangeset for help on using the changeset viewer.