Monday, August 05, 2013

Skype hangs due to removable media

So... on OS X, you can get Skype 6.6.0.467 (as well as the latest version 6.7.0.343) to hang all the time by doing the following.

  1. Mount a removable file system, such as a disk image.
  2. Send a file from that removable file system to someone else.
  3. Close Skype --- this is just so that you can...
  4. Eject the removable file system.
  5. Reopen Skype, and look at the chat history for the contact you sent the file to.
Skype then hangs.  However, if at this point you remount the removable file system and reopen Skype, then the chat history for your contact works and Skype doesn't hang.

It looks like the complete path of such files is stored in main.db under ~/Library/Application Support/Skype.  That file looks like sqlite, so no you don't get to deal with a text file you can edit with vi and at least work around the problem.

So how do you work around the issue?  Do you, like, delete all history for all contacts?  Or delete all history for that contact?  And you have to do this simply because you sent a contact a file from a removable device that has since been removed?  And you have to keep in mind that you can only remove the removable device after closing Skype because otherwise you can't remove the removable device?  Nobody thought those file paths might no longer be accessible at some point in a (say) 5 year chat history?

Seriously?

2 comments:

shingarov said...

I would say sqlite is not that much different from plain text. After all, you still need vi (or emacs, or something) to access plain text. This reminds me of those Smalltalk customers who were scared of ENVY because "what if ENVY eats all my source code, I can't use vi to retrieve it". Well... you still do trust your filesystem enough that you don't constantly keep the thought of block-level access to mass storage "in case the filesystem eats all my files" in the back of you head, right?

With that said, no before today I haven't looked at how Skype stores data, but now your post has made me curious.

% cd ~/Library/Application\ Support/Skype/boris.shingarov/
% file main.db
main.db: SQLite 3.x database
%

Ok, so this is an sqlite database. Let's investigate a bit more...

% sqlite3 main.db
SQLite version 3.7.12 2012-04-03 19:43:07
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .tables
Accounts ChatMembers DbMeta Transfers
Alerts Chats LegacyMessages VideoMessages
AppSchemaVersion ContactGroups Messages Videos
CallMembers Contacts Participants Voicemails
Calls Conversations SMSes
sqlite> .schema Messages
CREATE TABLE Messages (id INTEGER NOT NULL PRIMARY KEY, is_permanent INTEGER, convo_id INTEGER, chatname TEXT, author TEXT, from_dispname TEXT, author_was_live INTEGER, guid BLOB, dialog_partner TEXT, timestamp INTEGER, type INTEGER, sending_status INTEGER, consumption_status INTEGER, edited_by TEXT, edited_timestamp INTEGER, param_key INTEGER, param_value INTEGER, body_xml TEXT, identities TEXT, reason TEXT, leavereason INTEGER, participant_count INTEGER, error_code INTEGER, chatmsg_type INTEGER, chatmsg_status INTEGER, body_is_rawxml INTEGER, oldoptions INTEGER, newoptions INTEGER, newrole INTEGER, pk_id INTEGER, crc INTEGER, remote_id INTEGER, call_guid TEXT, extprop_chatmsg_ft_index_timestamp INTEGER, extprop_chatmsg_is_pending INTEGER);
CREATE INDEX IX_Messages_call_guid ON Messages (call_guid);
CREATE INDEX IX_Messages_convo_id_timestamp_consumption_status_sending_status ON Messages (convo_id, timestamp, consumption_status, sending_status);
CREATE INDEX IX_Messages_remote_id ON Messages (remote_id);
CREATE INDEX IX_Messages_timestamp_chatname ON Messages (timestamp, chatname);
CREATE INDEX IX_Messages_timestamp_convo_id_type ON Messages (timestamp, convo_id, type);
sqlite> .schema Chats
CREATE TABLE Chats (id INTEGER NOT NULL PRIMARY KEY, is_permanent INTEGER, name TEXT, options INTEGER, friendlyname TEXT, description TEXT, timestamp INTEGER, activity_timestamp INTEGER, dialog_partner TEXT, adder TEXT, type INTEGER, mystatus INTEGER, myrole INTEGER, posters TEXT, participants TEXT, applicants TEXT, banned_users TEXT, name_text TEXT, topic TEXT, topic_xml TEXT, guidelines TEXT, picture BLOB, alertstring TEXT, is_bookmarked INTEGER, passwordhint TEXT, unconsumed_suppressed_msg INTEGER, unconsumed_normal_msg INTEGER, unconsumed_elevated_msg INTEGER, unconsumed_msg_voice INTEGER, activemembers TEXT, state_data BLOB, lifesigns INTEGER, last_change INTEGER, first_unread_message INTEGER, pk_type INTEGER, dbpath TEXT, split_friendlyname TEXT, conv_dbid INTEGER);
CREATE INDEX IX_Chats_activity_timestamp ON Chats (activity_timestamp);
CREATE INDEX IX_Chats_first_unread_message ON Chats (first_unread_message);
CREATE INDEX IX_Chats_is_bookmarked ON Chats (is_bookmarked);
CREATE INDEX IX_Chats_lifesigns ON Chats (lifesigns);
CREATE INDEX IX_Chats_mystatus ON Chats (mystatus);
CREATE INDEX IX_Chats_name ON Chats (name);
CREATE INDEX IX_Chats_participants ON Chats (participants);
CREATE INDEX IX_Chats_type ON Chats (type);
sqlite>

Fun, isn't it?

Tod said...
This comment has been removed by a blog administrator.