Doing one thing after the other in a thread or not

Why this stupid title? Because I’ve got a crash showing that 2 things happen at the same time, which should happen one after the other.

On the click of a button in the toolbar a thread in started:

theArchiver = new ArchiveThread(some options) theArchiver.Run

The run event does

Archive Finish

where archive adds data to a database and finish does a diagnosis of the database. Today I got a crash log with the following information:

[code]10 com.mothsoftware.mailarchiverx 0x007be06a VField.FindValue%o%ovoi4 + 133
11 com.mothsoftware.mailarchiverx 0x00c98109 MailParser.CheckMailUnique%b%os + 466
12 com.mothsoftware.mailarchiverx
13 com.mothsoftware.mailarchiverx

  • 7293
    14 com.mothsoftware.mailarchiverx ArchiveThread.Event_Run%%o + 67
    [/code]

and

8 libvkernel_fat_release.dylib 0x09eb5231 fbl::Database_imp::Diagnose(fbl::smart_ptr<fbl::I_Location>, fbl::EVerboseLevel) + 73 9 v4rb_cocoa.dylib 0x0994d69a Database_Diagnose(REALobjectStruct*, int, REALobjectStruct*) + 341 10 com.mothsoftware.mailarchiverx 0x007a1364 VDatabase.Diagnose%b%o<VDatabase>i4o<FolderItem> + 90 11 com.mothsoftware.mailarchiverx 0x00b98aa6

which indicates to me the adding to the database and doing a diagnosis happen at the same time. Which isn’t allowed. in But how can this be?

Mac OS 10.11, Xojo 2015r4.

If “Archive” is a Thread, this should be expected.

Nope, “archive” is a method. I try to keep my messes as small as possible. One thread is more than enough complexity. Also, the problem occurs only for a very low number of users.

Is it possible that Archiver is running more than 1 time and that another instance of Archiver is calling Finish while the next Archiver is still working?

Maybe, instead of running Finish from within ArchiveThread you could start a Timer from within ArchiveThread and this Timer will run in Multiple Mode checking if any Archive is running before starting a Finish Thread?

Archiver is running only once. At the end of archiving there is a notification back to the model class. This class can check if the archive thread is still running or not and then initiate the diagnosis.

But I’d still like to understand what the §$%& is happening here.

I would start checking if the Notification System is working reliable in all cases and then if the Check for a running Archive Thread could fail in any case.

Are there any timers active ?

Maybe it’s a thread owned by SQLite. Do the headings in the crash log say that these happen in different threads?
Does it happen every time? Only with large db’s or specific SQLite version?
Just guessing but maybe the SQLite is still finishing writing and this writing happens in another thread?

Also make sure the button can only be clicked once so the thread can’t be fired multiple times.

@Jeff: no timers

@Marco: I’m hoping for guesses because the code is very complicated.

  • The threads both access Valentina, which makes the crash. Yes, it’s different threads.
  • Doesn’t happen every time. Just a very low number of users have had this problem. Don’t know about the size of the database.
  • According to my code archiving should be done before diagnosing.
  • The button can be clicked only once. Checked again this morning.

@Sascha: at the moment the notification doesn’t play a role. It’s strict doing thing 1 and then thing 2 in one thread. Thing 2 creates another thread. Would that make a difference?

Post the entire crash log ?

[quote]It’s strict doing thing 1 and then thing 2 in one thread.
Thing 2 creates another thread.
Would that make a difference?[/quote]

Although you said you only have one thread going at at time, the above suggests the opposite.

Is this what is happening…?

Launch thread A
Thing 1 happens
Thing2 happens and launches another thread B … there are now two threads?
Thing2 ends… perhaps 2 threads still going
Thread A ends?
Thread B ends? – or vice versa

@Jeff: let me try to summarize (it’s a good portion of a >50k app):

  • Thing 1 adds data to a database. No more threads.

  • Thing 2 does a diagnosis of said database. This creates a second thread, which is called here and waits for the calling function:

    dim theDiagnoser as new DiagnoseThread(theDatabase)
    theDiagnoser.Run

    while not DiagnoseFinished
    app.SleepCurrentThread 1000
    wend

The diagnosis thread sends a notification to the calling function and sets DiagnoseFinished to true. The more I think about the problem the more I think that this is the root cause.

The crashlog is here: http://www.mothsoftware.com/downloads/crashlog.zip .

Sorry for the pdf, this is the way I got it from the customer.