Hammerspoon / hammerspoon

Staggeringly powerful macOS desktop automation with Lua
http://www.hammerspoon.org
MIT License
12.09k stars 582 forks source link

Unbounded memory leak #859

Closed junkblocker closed 8 years ago

junkblocker commented 8 years ago
hs.inspect(hs.wifi.interfaceDetails())

Hammerspoon goes into a spin and eventually uses up all system memory and/or gets killed.

asmagill commented 8 years ago

Hmmm... that works fine on my machine... how many wireless interfaces does your machine have? Usually it's just 1, but check hs.inspect(hs.wifi.interfaces()) to see what it reports. Try using one of the table entries it returns as the argument to interface details (e.g. hs.wifi.interfaceDetails("en0"))... if that works, then something is broken in the automatic interface detection.

Have you tried just hs.wifi.interfaceDetails() (i.e. without the inspector module)? Does it also hang?

If you can, when it next crashes, look in ~/Library/Logs/DiagnosticReports/ for files which start with "Hammerspoon" and double click on (or open) the newest one... it will open up in the Console application... look for the "Thread 0 Crashed::" line and paste the contents of that section into this thread... I need to figure out where it's looping or stalling and the easiest way will be to see the contents of the crash log.

junkblocker commented 8 years ago

how many wireless interfaces

Only one.

> hs.inspect(hs.wifi.interfaces())
{ "en0" }

hs.wifi.interfaceDetails('en0') does not show any problem.

hs.inspect(hs.wifi.interfaceDetails('en0')) has the leak.

Trace from the crash when I reported this:

Thread 4 Crashed:
0   libsystem_c.dylib               0x00007fff8d0b27a7 __abort + 177
1   libsystem_c.dylib               0x00007fff8d0b26f6 abort + 144
2   libsystem_malloc.dylib          0x00007fff94bfe396 szone_error + 626
3   libsystem_malloc.dylib          0x00007fff94bf40e9 small_malloc_from_free_list + 1093
4   libsystem_malloc.dylib          0x00007fff94bf0b64 szone_malloc_should_clear + 1411
5   libsystem_malloc.dylib          0x00007fff94bf6cc1 szone_memalign + 573
6   libsystem_malloc.dylib          0x00007fff94bf6a52 malloc_zone_memalign + 114
7   libobjc.A.dylib                 0x00007fff8c689824 (anonymous namespace)::AutoreleasePoolPage::autoreleaseNoPage(objc_object*) + 98
8   com.apple.CoreFoundation        0x00007fff8222b696 _CFAutoreleasePoolPush + 22
9   com.apple.CoreFoundation        0x00007fff822b4701 __CFTSDFinalize + 49
10  libsystem_pthread.dylib         0x00007fff92b8c3dc _pthread_tsd_cleanup + 555
11  libsystem_pthread.dylib         0x00007fff92b8bf63 _pthread_exit + 117
12  libsystem_pthread.dylib         0x00007fff92b8a582 _pthread_wqthread + 1293
13  libsystem_pthread.dylib         0x00007fff92b88341 start_wqthread + 13
asmagill commented 8 years ago

What was thread 0 doing? Thread 0 is where Hammerspoon (should) be running all of its lua code, and since you seem to be having the problem only when hs.inspect is involved, it should be something in the Lua or console rendering code that's having the problem.

junkblocker commented 8 years ago
Thread 0:: Dispatch queue: com.apple.main-thread
0   com.apple.CoreText              0x00007fff92e1ae22 TLine::NormalizeRange(CFRange, long*, long*) const + 74
1   com.apple.CoreText              0x00007fff92e1af63 TLine::SetLevelRange(CFRange, unsigned char, bool) + 251
2   com.apple.CoreText              0x00007fff92de5ba3 TBidiEngine::ReorderGlyphsInDirectionRange(TLine&, CFRange, CTWritingDirection) + 119
3   com.apple.CoreText              0x00007fff92de5b0b TBidiEngine::ReorderGlyphs(TLine&) + 359
4   com.apple.CoreText              0x00007fff92e36457 TRunEncoder::EncodeWithLineOptions(CTRun*, unsigned int) + 245
5   com.apple.CoreText              0x00007fff92dc7a65 TRunEncoder::Encode(_CTGlyphStorage*, CFRange, unsigned int, __CFDictionary const*) + 573
6   com.apple.CoreText              0x00007fff92dc7818 CTRunCreateMutableRunsWithStorageAndOptions + 191
7   com.apple.UIFoundation          0x00007fff8602a3fb -[NSATSGlyphStorage createCTTypesetter] + 723
8   com.apple.UIFoundation          0x00007fff86023b24 -[NSATSTypesetter _ctTypesetter] + 322
9   com.apple.UIFoundation          0x00007fff8602ee49 -[NSATSLineFragment layoutForStartingGlyphAtIndex:characterIndex:minPosition:maxPosition:lineFragmentRect:] + 92
10  com.apple.UIFoundation          0x00007fff86024b5c -[NSATSTypesetter _layoutLineFragmentStartingWithGlyphAtIndex:characterIndex:atPoint:renderingContext:] + 3418
11  com.apple.UIFoundation          0x00007fff86026b04 -[NSATSTypesetter layoutParagraphAtPoint:] + 167
12  com.apple.UIFoundation          0x00007fff85f73328 -[NSTypesetter _layoutGlyphsInLayoutManager:startingAtGlyphIndex:maxNumberOfLineFragments:maxCharacterIndex:nextGlyphIndex:nextCharacterIndex:] + 4189
13  com.apple.UIFoundation          0x00007fff85f749ed -[NSTypesetter layoutCharactersInRange:forLayoutManager:maximumNumberOfLineFragments:] + 245
14  com.apple.UIFoundation          0x00007fff86027959 -[NSATSTypesetter layoutCharactersInRange:forLayoutManager:maximumNumberOfLineFragments:] + 983
15  com.apple.UIFoundation          0x00007fff85ff0004 -[NSLayoutManager(NSPrivate) _fillLayoutHoleForCharacterRange:desiredNumberOfLines:isSoft:] + 1158
16  com.apple.UIFoundation          0x00007fff85ff99c2 _NSFastFillAllLayoutHolesForGlyphRange + 1479
17  com.apple.AppKit                0x00007fff8b6857b2 -[NSTextView(NSPrivate) _ensureLayoutCompleteForRect:withExtensionFactor:minimumExtensionDistance:repetitions:] + 526
18  com.apple.AppKit                0x00007fff8b6858bd -[NSTextView(NSPrivate) _ensureLayoutCompleteForRect:withExtension:] + 82
19  com.apple.AppKit                0x00007fff8b1cbb9d -[NSTextView prepareContentInRect:] + 203
20  com.apple.AppKit                0x00007fff8b6d3988 -[NSView _updateSuggestedContentRectToValue:] + 729
21  com.apple.AppKit                0x00007fff8b14a7df -[NSView _updateSuggestedContentRect] + 100
22  com.apple.AppKit                0x00007fff8b19ba81 -[NSView _updateSuggestedContentRectForVisibleRectChange] + 219
23  com.apple.AppKit                0x00007fff8b04a73f -[NSScrollView(NSRulerSupport) _handleBoundsChangeForSubview:] + 350
24  com.apple.AppKit                0x00007fff8b00c516 -[NSView _postBoundsChangeNotification] + 132
25  com.apple.AppKit                0x00007fff8b00c426 -[NSView translateOriginToPoint:] + 287
26  com.apple.AppKit                0x00007fff8b00a8fc -[NSClipView _immediateScrollToPoint:] + 1964
27  com.apple.AppKit                0x00007fff8b00a0a8 -[NSClipView scrollToPoint:] + 241
28  com.apple.AppKit                0x00007fff8b047c44 -[NSScrollView scrollClipView:toPoint:] + 75
29  com.apple.AppKit                0x00007fff8afef197 -[NSClipView _scrollTo:animateScroll:flashScrollerKnobs:] + 1692
30  com.apple.AppKit                0x00007fff8b1bca96 -[_NSScrollingConcurrentMainThreadSynchronizer _scrollToCononicalOrigin] + 1079
31  com.apple.AppKit                0x00007fff8b1bc577 -[_NSScrollingConcurrentMainThreadSynchronizer _synchronize:completionHandler:] + 174
32  com.apple.AppKit                0x00007fff8b1bc496 __80-[_NSScrollingConcurrentMainThreadSynchronizer initWithSharedData:constantData:]_block_invoke + 144
33  libdispatch.dylib               0x00007fff8bb6e40b _dispatch_client_callout + 8
34  libdispatch.dylib               0x00007fff8bb7e675 _dispatch_source_latch_and_call + 2235
35  libdispatch.dylib               0x00007fff8bb72a83 _dispatch_source_invoke + 983
36  libdispatch.dylib               0x00007fff8bb8172d _dispatch_main_queue_callback_4CF + 422
37  com.apple.CoreFoundation        0x00007fff822b19e9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
38  com.apple.CoreFoundation        0x00007fff822708dd __CFRunLoopRun + 1949
39  com.apple.CoreFoundation        0x00007fff8226fed8 CFRunLoopRunSpecific + 296
40  com.apple.HIToolbox             0x00007fff862a2935 RunCurrentEventLoopInMode + 235
41  com.apple.HIToolbox             0x00007fff862a276f ReceiveNextEventCommon + 432
42  com.apple.HIToolbox             0x00007fff862a25af _BlockUntilNextEventMatchingListInModeWithFilter + 71
43  com.apple.AppKit                0x00007fff8af1fefa _DPSNextEvent + 1067
44  com.apple.AppKit                0x00007fff8af1f32a -[NSApplication _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 454
45  com.apple.AppKit                0x00007fff8af13e84 -[NSApplication run] + 682
46  com.apple.AppKit                0x00007fff8aedd46c NSApplicationMain + 1176
47  org.hammerspoon.Hammerspoon     0x000000010f7a71d2 main + 34 (MJAppDelegate.m:202)
48  libdyld.dylib                   0x00007fff83bce5ad start + 1
asmagill commented 8 years ago

Well, I was hoping for something obvious, but I think that just looks like it's trying to update the frontmost view...

What version of Hammerspoon are you running (hs.processInfo.version)? Is it a custom build or a stock release?

Ok, well if hs.wifi.interfaceDetails() by itself doesn't crash (with or without the argument, it should be identical on a single wireless interface machine) then let's see what the following do:

a = hs.wifi.interfaceDetails()

-- this will just show the top-level fields and shouldn't crash if the above didn't...
hs.inspect(a, { depth = 1 })

-- if that's ok, try upping depth to 2... this will show us the number of entries in `cachedScanResults`, which I suspect is where the problem is, but without actually expanding them
hs.inspect(a, { depth = 2 })

-- to verify it's the cachedScanResults field, finally, try:
hs.inspect(a, { process = function(item, path) if path[#path] == 'cachedScanResults' then return "** ignoring scan results **" else return item end end })

If my suspicion is correct, these should all work, and the culprit is something which is unprintable, but missed by our filter code; or if the first and last hs.inspect work, but the second crashes, then it's a problem in the generation of the cachedScanResults field.

And if some other combination or none of those work, but a lone and non-assigning hs.wifi.interfaceDetails works, then I'll have to ponder some more over where the culprit likely is... in any case, any results should help narrow the likely culprit.

In the mean time, I'll look closer at the code which generates that field's data... as I recall it included some binary data fields and may need better filtering or error checking.

junkblocker commented 8 years ago

I run the latest master branch and don't do any modifications of my own. Yes, all of those worked.

> hs.processInfo.version
0.9.45

> hs.inspect(a, { depth = 1 })
{
  active = true,
  activePHYMode = "G",
  bssid = "xx:xx:xx:xx:xx:xx",
  cachedScanResults = {...},
  configuration = {...},
  countryCode = "XX",
  hardwareAddress = "xx:xx:xx:xx:xx:xx",
  interface = "en0",
  interfaceMode = "Station",
  noise = -96,
  power = true,
  rssi = -41,
  security = "WPA Personal Mixed",
  ssid = "Xxxxxxxxxx",
  ssidData = "Xxxxxxxxxx",
  supportedChannels = {...},
  transmitPower = 0,
  transmitRate = 54.0,
  wlanChannel = {...}
}

> hs.inspect(a, { depth = 2 })
{
  active = true,
  activePHYMode = "G",
  bssid = "xx:xx:xx:xx:xx:xx",
  cachedScanResults = { {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...} },
  configuration = {
    networkProfiles = {...},
    rememberJoinedNetworks = true,
    requireAdministratorForAssociation = false,
    requireAdministratorForIBSSMode = false,
    requireAdministratorForPower = false
  },
  countryCode = "XX",
  hardwareAddress = "xx:xx:xx:xx:xx:xx",
  interface = "en0",
  interfaceMode = "Station",
  noise = -96,
  power = true,
  rssi = -41,
  security = "WPA Personal Mixed",
  ssid = "Xxxxxxxxxx",
  ssidData = "Xxxxxxxxxx",
  supportedChannels = { {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...}, {...} },
  transmitPower = 0,
  transmitRate = 54.0,
  wlanChannel = {
    band = "2GHz",
    number = 7,
    width = "20MHz"
  }
}

> hs.inspect(a, { process = function(item, path) if path[#path] == 'cachedScanResults' then return "** ignoring scan results **" else return item end end })

{
  active = true,
  activePHYMode = "G",
  bssid = "xx:xx:xx:xx:xx:xx",
  cachedScanResults = "** ignoring scan results **",
  configuration = {
    networkProfiles = { {
        security = "WPA2 Personal",
        ssid = "Xxxxxxxxxx",
        ssidData = "Xxxxxxxxxx"
      }, {
        security = "WPA2 Enterprise",
        ssid = "fooooooo",
        ssidData = "fooooooo"
      }, {
        security = "WPA2 Personal",
        ssid = "Barrrrr-Barrrrrrr-Barr",
        ssidData = "Barrrrr-Barrrrrrr-Barr"
      } },
    rememberJoinedNetworks = true,
    requireAdministratorForAssociation = false,
    requireAdministratorForIBSSMode = false,
    requireAdministratorForPower = false
  },
  countryCode = "XX",
  hardwareAddress = "xx:xx:xx:xx:xx:xx",
  interface = "en0",
  interfaceMode = "Station",
  noise = -96,
  power = true,
  rssi = -41,
  security = "WPA Personal Mixed",
  ssid = "Xxxxxxxxxx",
  ssidData = "Xxxxxxxxxx",
  supportedChannels = { {
      band = "2GHz",
      number = 1,
      width = "20MHz"
    }, {
      band = "2GHz",
      number = 2,
      width = "20MHz"
    }, {
      band = "2GHz",
      number = 3,
      width = "20MHz"
    }, {
      band = "2GHz",
      number = 4,
      width = "20MHz"
    }, {
      band = "2GHz",
      number = 5,
      width = "20MHz"
    }, {
      band = "2GHz",
      number = 6,
      width = "20MHz"
    }, {
      band = "2GHz",
      number = 7,
      width = "20MHz"
    }, {
      band = "2GHz",
      number = 8,
      width = "20MHz"
    }, {
      band = "2GHz",
      number = 9,
      width = "20MHz"
    }, {
      band = "2GHz",
      number = 10,
      width = "20MHz"
    }, {
      band = "2GHz",
      number = 11,
      width = "20MHz"
    }, {
      band = "2GHz",
      number = 12,
      width = "20MHz"
    }, {
      band = "2GHz",
      number = 13,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 36,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 36,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 36,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 40,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 40,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 40,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 44,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 44,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 44,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 48,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 48,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 48,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 52,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 52,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 52,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 56,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 56,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 56,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 60,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 60,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 60,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 64,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 64,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 64,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 100,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 100,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 100,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 104,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 104,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 104,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 108,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 108,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 108,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 112,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 112,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 112,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 116,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 116,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 116,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 120,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 120,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 120,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 124,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 124,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 124,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 128,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 128,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 128,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 132,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 132,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 132,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 136,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 136,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 136,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 140,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 140,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 140,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 144,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 144,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 144,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 149,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 149,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 149,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 153,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 153,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 153,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 157,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 157,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 157,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 161,
      width = "80MHz"
    }, {
      band = "5GHz",
      number = 161,
      width = "40MHz"
    }, {
      band = "5GHz",
      number = 161,
      width = "20MHz"
    }, {
      band = "5GHz",
      number = 165,
      width = "20MHz"
    } },
  transmitPower = 0,
  transmitRate = 54.0,
  wlanChannel = {
    band = "2GHz",
    number = 7,
    width = "20MHz"
  }
}
asmagill commented 8 years ago

I assume the Xxx's are yours? Yeah, should have thought to mention that you should blurb anything that might be sensitive out, but I was focused on verifying that it is in fact with the rendering of the results of cachedScanResults. Ok, now I know where to focus my efforts...

Thanks! Hope to have a fix for you to test tomorrow -- will keep you posted!

junkblocker commented 8 years ago

Yes, I anonymized the data by hand. I am somewhat of a privacy nut :) Thanks!

asmagill commented 8 years ago

I wouldn't consider it being a nut, and I should have mentioned it myself, but I was thinking more about the code than about what would be posted at the time! No worries, I do it myself most of the time!

heptal commented 8 years ago

It would be funny if the culprit was a 'creative' SSID doing something nasty in CoreText, which has been known on more than one occasion to be susceptible.

junkblocker commented 8 years ago

:smile: Mine and the SSIDs around me all seem to fit /^[a-zA-Z0-9][a-zA-Z0-9_ -]+$/ .

asmagill commented 8 years ago

It looks like the issue might be related... the core thread is processing glyphs when the crash occurs...

What OS X version are you running and is it the latest security patch available for your version?

Also, try this in your console - you don't need to send the results, I just need to know if it crashes or not:

hs.inspect(hs.wifi.interfaceDetails().cachedScanResults, { process = function(item, path) if path[#path] == 'informationElementData' then return "** ignoring scan results **" else return item end end })

If this makes things safe again, then the simplest solution is to simply remove this field from the results... I don't think anyone is using it at present. The informationElementData contains "Information element data included in beacon or probe response frames."

My personal design philosophy is to give people access to everything and then let them do things with it that I haven't thought of yet. Application crashers are a reasonable exception, especially since, unfortunately, the code which would need to be fixed is in CoreText, which is at a lower level then the Cocoa APIs so we can't even swizzle in a replacement - we have to wait for an Apple patch.

If you confirm this is the culprit, I'll look into adding a function to retrieve this field and take it out of the default results... and then heavily document the new function about the possible dangers of treating it as displayable text, rather than as a binary blob in need of further parsing.

junkblocker commented 8 years ago

What OS X version are you running and is it the latest security patch available for your version?

I stay up to date on fixes and pretty much always running the latest of everything.

uname: Darwin excession 15.4.0 Darwin Kernel Version 15.4.0: Fri Feb 26 22:08:05 PST 2016; root:xnu-3248.40.184~3/RELEASE_X86_64 x86_64
OS:   darwin15.0.0 Mac OS X 10.11.4 (Build 15E65)
Arch: MacBookPro11,4

I am not on the same WiFi/Network as when I saw the crash. But the problem still occurred. No the code fragment did not crash.

There is another possible issue I just realized which may be related. Somehow in the past few day when I arrive at work, I get the auth dialog for connecting to a WiFi network but no indication what that network is or why the machine should be trying to connect to it. My usual saved work network connects fine by itself meanwhile. This turned out to be 802.1X PNAC they pushed out.

cmsj commented 8 years ago

I did a bit of research on that field, it's Element ID 221 in the 802.11 specification, and it's 253 bytes of vendor specific information, so it really could be anything (there are some great research papers that suggest using it as a communications channel for unassociated devices!) and I suspect the easiest option would be to remove it.

I've not been able to find any code that parses these things, but since they're vendor specific anyway, there could be umpteen possible data formats.

I suggest we drop the field - anyone doing something sufficiently advanced that they need it, can ask for it to be added and supply code to make it safe :)

asmagill commented 8 years ago

I have a fix I'm testing and plan to push later tonight. The field is made available through another function and isn't returned by anything else anymore.

heptal commented 8 years ago

It would be interesting to know the contents of the blob in question as a CoreText rendering bug is fairly severe and should just display boxes or whatever when fed garbage. The 'real' solution would be to get it fixed upstream, IMO.

asmagill commented 8 years ago

If you can, check out the pull request; otherwise sounds like @cmsj wants to do a new release within the next day or so and this will be in master by then.

Some suggestions on how you might display the actual content of the field safely are in the updated docs for hs.wifi.backgroundScan... I too would be curious what the contents are if you can track down the specific culprit! :-)

junkblocker commented 8 years ago

That worked, @asmagill ! I'll see when I can get that info for you unless you wanna give me a code fragment that will dump it. ;)

junkblocker commented 8 years ago

@asmagill , I am not a Lua guy so couldn't get your debug comment to work exactly. But I've created a dump using this

function ifo()
    local cachedScanResults = hs.wifi.interfaceDetails('en0').cachedScanResults

    for i = 1, #cachedScanResults do
        print(table.concat(hs.fnutils.map(table.pack(cachedScanResults[i].informationElementData)[1], function(x) return hs.utf8.asciiOnly(string.char(x)) end), ''))
    end
end

Let me know where I can send it to you privately. Also there is at least one typo in your fix comment us vs hs.

asmagill commented 8 years ago

I'm adding the following to the documentation as an example (and I'll fix the typo, thanks!):

function dumpIED(interface)
    local interface = interface or "en0"
    local cleanupFunction = hs.utf8.hexDump -- or hs.utf8.asciiOnly if you prefer

    local cachedScanResults = hs.wifi.interfaceDetails(interface).cachedScanResults
    if not cachedScanResults then
        hs.wifi.availableNetworks() -- blocking, so only do if necessary
        cachedScanResults = hs.wifi.interfaceDetails(interface).cachedScanResults
    end

    for i, v in ipairs(cachedScanResults) do
        print(string.format("%s on channel %d -- informationElementData:", v.ssid, v.wlanChannel.number))
        print(cleanupFunction(string.char(table.unpack(v.informationElementData))))
    end
end

Let me see about setting up a drop box on my ownCloud server, and I'll let you know about transferring the data for further review. Thanks!

asmagill commented 8 years ago

Hmmm I assumed ownCloud would support that...

At any rate, you can upload to https://dropitto.me/asmagillDropBox, password "hammerspoon". It's a one way thing -- you can only upload, and I'll remove the file from the cloud store as soon as I get an email that it's been transferred... so, if you're still game to let me look at the raw data, I'll see if I can isolate exactly what is causing the crashing.

However, I think the immediate Hammerspoon concern -- the crashing -- is fixed with the update, and as soon as I get the typos fixed and figure out why Travis is now balking at the test suite (which I didn't touch, so I'm at a loss until I look at it some more), I'll get these changes added to Master so they make it in the next release.

junkblocker commented 8 years ago

Sent

asmagill commented 8 years ago

Got it! Thanks! Will let you know what I find... I'd really like to be able to figure out exactly what triggers the crash and add a filter to the console display code -- all we've really done is make it more difficult for someone to trigger it by accident... but, we'll see!

cmsj commented 8 years ago

This should be fixed by fe219dd7f34e311da5345059add035008754ee8d