omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Segmentation fault using dialogs

    Pythonista
    3
    33
    385
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • bosco
      bosco last edited by

      @LankyDonkey I'm starting a new thread for your music app issues.

      I'm glad you're not crashing after disabling garbage collection. This indicates that some objects / variables that are deleted while still in use. Changing a local variable to a variable in your main class or pointing to a global variable may fix your problem without needing to disable garbage collection.

      @ui.in_background
      def do_filter(self, sender):
          self.form_list_of_section = 'some data'
      

      or

      global form_list_of_section
      
      @ui.in_background
      def do_filter(sender):
          global form_list_of_section
          form_list_of_section = 'some data'
      

      I create a simple script here uimusic that uses dialogs, sqlite and MPMediaQuery. You may find it useful.

      1 Reply Last reply Reply Quote 0
      • bosco
        bosco last edited by

        @LankyDonkey New thread for your app.

        1 Reply Last reply Reply Quote 0
        • LankyDonkey
          LankyDonkey last edited by LankyDonkey

          Thank you Bosco - to give more detail of my dialog code i have the following setup

          MAINSCRIPT.py

          import FilterDialog
          class MainViewer(ui.View): 
                  def__init__(self):
                         self.filter_data = dict(genre="", year=None)
                         self.filter_button.action=handle_filter
                 
                  def handlefilter(self):
                         res = FilterDialog.display(self.filter_data)
                         if res: 
                                self.filter_data = res 
          

          FILTERDIALOG.PY

          import dialogs
          def display(filter_data):
               #create form_list_sections from filter_data
               diag = dialogs.form_dialog(sections=form_list_of_sections)
               #do some verification checks and then convert data back into
              #filter_data format and then return
          

          so somewhere i believe filter_data must be getting garbage collection but I am not sure why. In my case above where would i define self.filter_data to be global?

          LankyDonkey 1 Reply Last reply Reply Quote 0
          • LankyDonkey
            LankyDonkey @LankyDonkey last edited by

            @LankyDonkey I just did some more testing and the segmentation fault is back in dialogs.py line 372 in done_action. So it looks like maybe the garbage collection is not the solution i thought it was. I will take a look into the uimusic.py you created and see if there is something you are doing that I can adapt in my solution.

            bosco 1 Reply Last reply Reply Quote 0
            • bosco
              bosco @LankyDonkey last edited by bosco

              @LankyDonkey
              add @ui.in_background

              class MainViewer(ui.View): 
                 def __init__(self):
                     self.filter_data = dict(genre="", year=None)
                     self.filter_button.action=handle_filter
                  
                  @ui.in_background       
                  def handlefilter(self, sender):
                     res = FilterDialog.display(self.filter_data)
                     if res: 
                        self.filter_data = res
              
              
              LankyDonkey 1 Reply Last reply Reply Quote 0
              • LankyDonkey
                LankyDonkey @bosco last edited by

                @bosco at the moment i have @on_main_thread but i have also decorated with @ui.in_background but the error still occurs

                LankyDonkey 1 Reply Last reply Reply Quote 0
                • LankyDonkey
                  LankyDonkey @LankyDonkey last edited by

                  @LankyDonkey i dont really understand the on_main_thread or ui.in_background but I have tried to decorate just the methods that launch dialogs with each of them and then when that didnt work i decorated all the other methods but the problem still remains.

                  bosco 1 Reply Last reply Reply Quote 0
                  • bosco
                    bosco @LankyDonkey last edited by bosco

                    This post is deleted!
                    LankyDonkey 1 Reply Last reply Reply Quote 0
                    • LankyDonkey
                      LankyDonkey @bosco last edited by

                      @bosco sorry that was my mistake - it is indented and part of my MainViewer - I just made a mistake when i typed into - i do have sender in there as well but i left that out for simplicity. so code is just as you have it

                      bosco 1 Reply Last reply Reply Quote 0
                      • bosco
                        bosco @LankyDonkey last edited by

                        @LankyDonkey Do you ever get the dialog error the first time or only after self.filter_data becomes more complex?

                        FilterDialog.py

                        global keepme
                        keepme = None
                        
                        def display(some_data):
                            #add some data to sections
                            global keepme
                            keepme = form_list_of_sections
                            print(form_list_of_sections)
                            diag = dialogs.form_dialog(title="Filter", sections=form_list_of_sections)
                            #format result data and return
                        
                        LankyDonkey 1 Reply Last reply Reply Quote 0
                        • LankyDonkey
                          LankyDonkey @bosco last edited by LankyDonkey

                          @bosco i do sometimes get it the very first time i use the filter. I also get it when using simpler filters. I am not sure if this would help but i pasted a cut down copy of my app code here
                          It doesnt have any music playing code - its just a database and gui but it still crashes. Maybe you can see something really obvious I am doing. The code is started from the songsviewer.py file

                          bosco 1 Reply Last reply Reply Quote 0
                          • bosco
                            bosco @LankyDonkey last edited by bosco

                            @LankyDonkey Great! I'll try your code.
                            Have you tried the global variable I put in my last post?

                            I did get your code to crash a couple times. I'm going to be offline for a few hours, but I'll look at it later.

                            bosco 1 Reply Last reply Reply Quote 0
                            • bosco
                              bosco @bosco last edited by bosco

                              @bosco This is one change I would make.

                              class MyListDataSource(ui.ListDataSource):
                                  def __init__(self, items, *args, **kwargs ):
                                      ui.ListDataSource.__init__(self, items, *args, **kwargs)
                                      self.width = ui.get_screen_size()[0]
                                      self.refresh(items)
                                      
                                  def refresh(self, items):
                                      self.all_items = items['items']
                                      self.quiz_mode = items['quiz_mode']
                                      self.font_size=items['font_size']
                                      #self.items = [f"{index+1}.{item['title']} {item['artist']} {item['year']} [{item['rating']}] [{item['timeplayed']}]" for index, item in enumerate(self.all_items)]
                                      self.items = [f"{item['title']} {item['artist']} {item['year']} {item['score']} {item['album']}" for index, item in enumerate(self.all_items)]
                              
                              class SongViewer(ui.View):
                                  
                                  def __init__(self,songs):
                                      # stuff...
                                      # define self.song_titles once
                                      self.song_titles = MyListDataSource(dict(items = self.songs, quiz_mode = False, context = None, font_size = self.font_size))
                                      # more stuff...
                              
                                  #!! @on_main_thread
                                  def refresh_playlist(self):
                                      if self.playlist_filter:
                                          self.songs = self.MDB.apply_filter_2(self.playlist_filter, None)
                                          self.db_songs = self.songs
                                          self.refresh_songs()
                                      
                                  def refresh_songs(self):
                                      # refresh datasource items
                                      self.song_titles.refresh(dict(items = self.songs, quiz_mode = self.quiz_mode, context = None, font_size = self.font_size))
                                      # ui.ListDataSource will auto reload when items change
                                      # skip code below
                                      """
                                      self.table.data_source = self.table.delegate = self.song_titles 
                                      self.song_titles.action=self.cell_tapped
                                      self.info.text=f"\n{self.get_playlist_filter_string()}"
                                      self.table.reload()
                                      """
                              

                              I've been testing by clicking the filter_button, changing the 'from year' and 'done'. Should that be enough to make it crash?

                              LankyDonkey 2 Replies Last reply Reply Quote 0
                              • LankyDonkey
                                LankyDonkey @bosco last edited by

                                @bosco yes that would make it crash - i can make it crash by selecting any random item in filter dialog - i can also make it crash by clicking the G! button and making changes or the long button at the bottom that displays Genres and making some changes there. I will make the changes you mention above. I did add the global variable into the dialog files but it still crashes. Thank you

                                LankyDonkey 1 Reply Last reply Reply Quote 0
                                • LankyDonkey
                                  LankyDonkey @LankyDonkey last edited by

                                  @LankyDonkey I made the changes to MyListDataSource - it still crashes but I can see this is a much better way of refreshing the data. Another strange thing I keep noticing is random items will occasionally disappear from my dialogs - for example under the charts section of the filter dialog 50s might disappear and then when i re-open it will be there. very strange.

                                  LankyDonkey 1 Reply Last reply Reply Quote 0
                                  • LankyDonkey
                                    LankyDonkey @LankyDonkey last edited by

                                    @LankyDonkey Whats odd is that I can use dialogs fine and then when the app is playing some songs and even if I haven't used any dialogs for a while it will suddenly crash - could it be that using the dialogs is making the app unstable - maybe it messes with the memory structure and then a later part of the app overwrites that memory causing a seg fault. So it may not be the action I do at the time that causes the crash but a previous action that has put it into an unstable state. I don't really understand these segmentation faults but it appears to be related to memory being used that shouldnt.

                                    1 Reply Last reply Reply Quote 0
                                    • LankyDonkey
                                      LankyDonkey @bosco last edited by LankyDonkey

                                      @bosco Hi Bosco I have added additional log information into my code and I can confirm that the crash happens inside the dialogs.form_dialog() call - I have code either side of the call that writes to the database with the contents of form_list_of_sections and I can see the data is fine going into the function call. I have code immediatly after the function call to add further logging to the database but this code is never reached. To me this seems like a problem with pythonista itself as there is nothing wrong with the data going in but the function never returns - it crashes on the done button( In looking dialog.py i notice the line that it crashes on is ui.end_editing()). Would you agree with this assessment?

                                      bosco 1 Reply Last reply Reply Quote 0
                                      • bosco
                                        bosco @LankyDonkey last edited by

                                        @LankyDonkey I completely agree!
                                        I thought I had a work around several times, but it still crashes. This test replacement for FilterDialog.py uses static filter data and returns static result data. It doesn't even return the results from the dialog.

                                        If you comment out this line

                                        #c.tableview_cell_for_row = tableview_cell_for_row
                                        

                                        and then scroll down in the dialog and select 'Speed: S4', it crashed for me every time.

                                        import time, pprint
                                        import dialogs
                                        import emoji
                                        
                                        sections = [
                                            ('Special Filters',
                                                [
                                                {'key': 'limit',
                                                'title': 'Artist Limit (00 for None):  ',
                                                'type': 'number',
                                                'value': '30'},
                                                {'key': 'country_count', 'title': 'Country Count:  ', 'type': 'check'}
                                                ]),
                                            ('Year Range',
                                                [
                                                {'key': 'year_from',
                                                'title': 'Year From:  ', 'type': 'number', 'value': '1990'},
                                                {'key': 'year_to', 'title': 'Year To:  ', 'type': 'number', 'value': '2022'},
                                                {'key': 'one_song', 'title': 'One Song:  ', 'type': 'check', 'value': False},
                                                ]),
                                            ('Rating',
                                                [
                                                {'title': '1', 'type': 'check'},
                                                {'title': '2', 'type': 'check'},
                                                {'title': '3', 'type': 'check'},
                                                {'title': '4', 'type': 'check'},
                                                {'title': '5', 'type': 'check'},
                                                {'title': '6', 'type': 'check'},
                                                {'title': '7', 'type': 'check'},
                                                {'title': '8', 'type': 'check'},
                                                {'title': '9', 'type': 'check'},
                                                {'title': '10', 'type': 'check'},
                                                {'title': '11', 'type': 'check'},
                                                {'title': '12', 'type': 'check'}
                                                ]),
                                            ('Speed',
                                                [
                                                {'title': 'S5', 'type': 'check'},
                                                {'title': 'S4', 'type': 'check'}
                                                ])
                                        ]
                                        
                                        
                                        filter = {'best_years': False,
                                         'charts': [],
                                         'countries': [],
                                         'country_count': False,
                                         'genres': [],
                                         'missing_pos': None,
                                         'missing_song_info': False,
                                         'occasions': [],
                                         'one_song': False,
                                         'popularity': [],
                                         'pos_from': None,
                                         'pos_to': None,
                                         'rating': [],
                                         'song_info': False,
                                         'special_filters': {'best_albums': False,
                                                             'best_artists': False,
                                                             'country_count': False,
                                                             'limit': '30',
                                                             'one_hit_wonders': False},
                                         'speeds': [],
                                         'sub_and': False,
                                         'subgenres': [],
                                         'tempos': [],
                                         'us_pos_from': None,
                                         'us_pos_to': None,
                                         'xmas': False,
                                         'year_from': '1990',
                                         'year_to': '2022'}
                                         
                                        
                                        retaincells = {}
                                        
                                        def display(playlist_filter):
                                        
                                            def tableview_cell_for_row(tv, section, row):
                                                sel_item = c.sections[section][1][row]
                                                key = sel_item['key']
                                                cell = c.cells[section][row]
                                                retaincells[key] = cell
                                                return cell
                                            
                                            #diag = dialogs.form_dialog(title = 'Song Filter', sections=sections)
                                            c = dialogs._FormDialogController('Song Filter', sections, done_button_title='Done')
                                            c.tableview_cell_for_row = tableview_cell_for_row
                                            c.container_view.present('sheet')
                                            c.container_view.wait_modal()
                                            if c.was_canceled:
                                                return None
                                            else:
                                                diag = c.values
                                            c.container_view = None
                                            
                                            pprint.pprint(diag)
                                            time.sleep(2)
                                            return filter
                                        
                                        

                                        I'm going to try to create a very simple script to duplicate the issue that we can show @omz

                                        LankyDonkey 1 Reply Last reply Reply Quote 0
                                        • LankyDonkey
                                          LankyDonkey @bosco last edited by

                                          @bosco Thats great that you can repeat the crash everytime - this is something I have been trying to do but no success so far as it has been random for me. I hope you can create the simple script to isolate problem as that would be a big step forward. Thanks

                                          bosco 1 Reply Last reply Reply Quote 0
                                          • bosco
                                            bosco @LankyDonkey last edited by

                                            @LankyDonkey Can you confirm that this script crashes when you run it multiple times after scrolling down?

                                            #inport gc
                                            #gc.disable()
                                            import time, pprint
                                            import dialogs
                                            import objc_util
                                            
                                            retaincells = {}
                                            
                                            try_fix = False
                                            """
                                            Dupicate issue:
                                            set try_fix = False
                                            run script
                                            scroll to RATING section, select 3, click Done
                                              or
                                            scroll unitl RATING section is a the top of the view.
                                              (larger phone may require more scrolling.  
                                            rerun script
                                            It will usually crash when run the 2nd or 3rd time.
                                            """
                                            
                                            def cleanup():
                                                for key in retaincells.keys():
                                                    print(2, key)
                                                    objc_util.release_global(retaincells[key].objc_instance)
                                            
                                            sections = [('Special Filters',
                                              [{'key': 'limit', 'title': 'Artist Limit (0 for None):',
                                                'type': 'number', 'value': '30'},
                                               {'key': 'country_count', 'title': 'Country Count:  ', 'type': 'check'},
                                               {'key': 'best_artists', 'title': 'Best Artists:  ', 'type': 'check'},
                                               {'key': 'best_albums', 'title': 'Best Albums:  ', 'type': 'check'},
                                               {'key': 'best_genres', 'title': 'Best Genres:  ', 'type': 'check'},
                                               {'key': 'best_years', 'title': 'Best Years:  ', 'type': 'check'},
                                               {'key': 'best_decades', 'title': 'Best Decades:  ', 'type': 'check'},
                                               {'key': 'one_hit_wonders', 'title': 'One Hit Wonders:  ', 'type': 'check'} ]),
                                             ('Year Range',
                                              [{'key': 'year_from', 'title': 'Year From:', 'type': 'number', 'value': '1990'},
                                               {'key': 'year_to', 'title': 'Year To:  ', 'type': 'number', 'value': '2022'},
                                               {'key': 'one_song', 'title': 'One Song:  ', 'type': 'check', 'value': False},
                                               {'key': 'missing_song_info', 'title': 'Missing Song Info:',
                                                       'type': 'check', 'value': False},
                                               {'key': 'song_info', 'title': 'Song Info:', 'type': 'check', 'value': False},
                                               {'key': 'sub_and', 'title': 'Subgenre AND:', 'type': 'check', 'value': False},
                                               {'key': 'xmas', 'title': 'Include Xmas Songs?', 'type': 'check', 'value': False},
                                               {'key': 'pos_from', 'title': 'Pos From:  ', 'type': 'number', 'value': ''},
                                               {'key': 'pos_to', 'title': 'Pos To:', 'type': 'number', 'value': ''},
                                               {'key': 'missing_pos', 'title': 'Missing Pos:', 'type': 'check', 'value': False},
                                               {'key': 'us_pos_from', 'title': 'US Pos From:  ', 'type': 'number', 'value': ''},
                                               {'key': 'us_pos_to', 'title': 'US Pos To:', 'type': 'number', 'value': ''}]),
                                             ('Rating',
                                              [{'title': '3', 'type': 'check'},
                                               {'title': '4', 'type': 'check'},
                                               {'title': '5', 'type': 'check'}]),
                                             ('Speed',
                                              [{'title': 'S5', 'type': 'check'},
                                               {'title': 'S4', 'type': 'check'},
                                               {'title': 'S3', 'type': 'check'},
                                               {'title': 'S2', 'type': 'check'},
                                               {'title': 'S1', 'type': 'check'},
                                               {'title': 'Missing', 'type': 'check'}]),
                                             ('Popularity',
                                              [{'title': '[10]', 'type': 'check'},
                                               {'title': '[9]', 'type': 'check'},
                                               {'title': '[8]', 'type': 'check'},
                                               {'title': '[7]', 'type': 'check'},
                                               {'title': '[6]', 'type': 'check'},
                                               {'title': '[5]', 'type': 'check'},
                                               {'title': '[4]', 'type': 'check'},
                                               {'title': '[3]', 'type': 'check'},
                                               {'title': '[2]', 'type': 'check'},
                                               {'title': '[1]', 'type': 'check'},
                                               {'title': '[0]', 'type': 'check'}]),
                                             ('Charts',
                                              [{'title': '50s', 'type': 'check'},
                                               {'title': '60s', 'type': 'check'},
                                               {'title': '70s', 'type': 'check'},
                                               {'title': '80s', 'type': 'check'},
                                               {'title': '90s', 'type': 'check'},
                                               {'title': '2000s', 'type': 'check'},
                                               {'title': '2010s', 'type': 'check'},
                                               {'title': '2020s', 'type': 'check'}]),
                                             ('Genres',
                                              [{'title': 'Rock', 'type': 'check'},
                                               {'title': 'Pop', 'type': 'check'},
                                               {'title': 'Indie', 'type': 'check'},
                                               {'title': 'Rap', 'type': 'check'},
                                               {'title': 'Thrash', 'type': 'check'},
                                               {'title': 'Country', 'type': 'check'},
                                               {'title': 'Dance', 'type': 'check'},
                                               {'title': 'Disco', 'type': 'check'},
                                               {'title': 'Soul', 'type': 'check'},
                                               {'title': 'Post-punk', 'type': 'check'},
                                               {'title': 'Punk', 'type': 'check'}]),
                                             ('Sub Genres',
                                              [{'title': 'Aor', 'type': 'check'},
                                               {'title': 'Modernindie', 'type': 'check'},
                                               {'title': 'Modernrock', 'type': 'check'},
                                               {'title': 'Summer', 'type': 'check'},
                                               {'title': 'Classicrock', 'type': 'check'},
                                               {'title': 'Northernsoul', 'type': 'check'},
                                               {'title': 'Indierock', 'type': 'check'},
                                               {'title': 'Drumnbass', 'type': 'check'},
                                               {'title': 'Funk', 'type': 'check'},
                                               {'title': 'Hairmetal', 'type': 'check'},
                                               {'title': 'Blues', 'type': 'check'},
                                               {'title': 'Reggae', 'type': 'check'},
                                               {'title': 'Breakdance', 'type': 'check'},
                                               {'title': 'Garage', 'type': 'check'},
                                               {'title': 'Heavymetal', 'type': 'check'},
                                               {'title': 'House', 'type': 'check'},
                                               {'title': 'Cheese', 'type': 'check'},
                                               {'title': 'Billy', 'type': 'check'},
                                               {'title': 'Grime', 'type': 'check'},
                                               {'title': 'Rare', 'type': 'check'},
                                               {'title': 'Yachtrock', 'type': 'check'},
                                               {'title': 'Synthpop', 'type': 'check'}]),
                                             ('Occasions',
                                              [{'title': 'Christmas', 'type': 'check'},
                                               {'title': 'Bonfire', 'type': 'check'},
                                               {'title': 'Halloween', 'type': 'check'},
                                               {'title': 'Birthday', 'type': 'check'}]),
                                             ('Tempo',
                                              [{'title': 'Slow', 'type': 'check'},
                                               {'title': 'Normal', 'type': 'check'},
                                               {'title': 'Fast', 'type': 'check'},
                                               {'title': 'Not slow', 'type': 'check'}])]
                                            
                                            xfilter = {'best_years': False,
                                             'charts': [],
                                             'countries': [],
                                             'country_count': False,
                                             'genres': [],
                                             'missing_pos': None,
                                             'missing_song_info': False,
                                             'occasions': [],
                                             'one_song': False,
                                             'popularity': [],
                                             'pos_from': None,
                                             'pos_to': None,
                                             'rating': [],
                                             'song_info': False,
                                             'special_filters': {'best_albums': False,
                                                                 'best_artists': False,
                                                                 'country_count': False,
                                                                 'limit': '30',
                                                                 'one_hit_wonders': False},
                                             'speeds': [],
                                             'sub_and': False,
                                             'subgenres': [],
                                             'tempos': [],
                                             'us_pos_from': None,
                                             'us_pos_to': None,
                                             'xmas': False,
                                             'year_from': '1990',
                                             'year_to': '2023'}
                                            
                                            def display(playlist_filter):
                                                cleanup()
                                                retaincells.clear()    
                                                
                                                def tableview_cell_for_row(tv, section, row):
                                                    sel_item = c.sections[section][1][row]
                                                    key = sel_item['key']
                                                    cell = c.cells[section][row]
                                                    retaincells[key] = cell
                                                    objc_util.retain_global(cell.objc_instance)
                                                    return cell
                                            
                                                if try_fix:    
                                                    print('form dialog semi-fix')
                                                    c = dialogs._FormDialogController('Song Filter', sections, done_button_title='Done')
                                                    c.tableview_cell_for_row = tableview_cell_for_row
                                                    c.container_view.present('sheet')
                                                    c.container_view.wait_modal()
                                                    if c.was_canceled:
                                                        diag = None
                                                    else:
                                                        diag = c.values
                                                    c.container_view = None
                                                else:
                                                    print('form dialog standard')
                                                    diag = dialogs.form_dialog(title = 'Song Filter', sections=sections)
                                                    
                                                print('done')
                                                time.sleep(1)
                                                return xfilter
                                                
                                             
                                            if __name__ == '__main__':    
                                                result = display(None)
                                                print(result['year_to'])
                                            
                                            LankyDonkey 1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post
                                            Powered by NodeBB Forums | Contributors