Skip to content

Calling performSelector for a @objc_method created by rubicon from Objective C crashes in Python 3.9 #223

@yilei

Description

@yilei

Describe the bug
In Python 3.9, calling [obj performSelector:NSSelectorFromString(@"name")] crashes with EXC_BAD_ACCESS (code=2, address=0x1056f7f48) if the obj is an instance of a class created by rubicon with @objc_method def name(self): ....

To Reproduce
Steps to reproduce the behavior:

  1. Create a briefcase iOS project:
    $ briefcase new
    # Give it a name `py39crashdemo`
    $ cd py39crashdemo
    $ briefcase create iOS
    
  2. Add the objc class definition using rubicon in app.py:
    $ cat iOS/Xcode/py39crashdemo/py39crashdemo/app/py39crashdemo/app.py
    """
    My first application
    """
    from rubicon import objc
    class Runner(objc.NSObject):
        @objc.objc_method
        def execScript(self):
            pass
    def main():
        # This should start and launch your app!
        Interop = objc.ObjCClass("Interop")  # Interop is a class defined in objc.
        Interop.sharedRunner = Runner.alloc().init()
    
  3. Add the objective code that invokes the execScript method:
     $ cat iOS/Xcode/py39crashdemo/py39crashdemo/main.m
     //
     //  main.m
     //  A main module for starting Python projects under iOS.
     //
     
     #import <Foundation/Foundation.h>
     #import <UIKit/UIKit.h>
     #include <Python.h>
     #include <dlfcn.h>
     
     NSObject *_sharedRunner;
     
     @interface Interop: NSObject
     @property(class) NSObject *sharedRunner;
     @end
     @implementation Interop
     + (void)setSharedRunner:(NSObject *)sharedRunner {
         _sharedRunner = sharedRunner;
     }
     + (NSObject *)sharedRunner {
         return _sharedRunner;
     }
     @end
     
     @interface PythonAppDelegate : NSObject<UIApplicationDelegate>
     @end
     @implementation PythonAppDelegate
     - (void)applicationDidFinishLaunching:(UIApplication *)application {
         [Interop.sharedRunner performSelector:NSSelectorFromString(@"execScript")];  // <---- This is the crash
     }
     @end
     
     int main(int argc, char *argv[]) {
     // ... below are untouched
    
  4. Run the iOS application, and it crashes with EXC_BAD_ACCESS (code=2, address=0x1056f7f48) at [Interop.sharedRunner performSelector:NSSelectorFromString(@"execScript")];

Expected behavior
It should not crash.

Environment:

  • Operating System: macOS 11.3
  • Python version: 3.9.4
  • Software versions:
    • Briefcase: 0.3.5
    • Xcode: 12.5
    • Toga: n/a
    • ...

Additional context
I had an earlier conversion on BeeWare Discoard with @freakboy3742, and I'm instructed to file this bug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA crash or error in behavior.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions