{ "id": "142541", "key": "TIMOB-19981", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [], "resolution": { "id": "7", "description": "", "name": "Invalid" }, "resolutiondate": "2015-12-07T22:48:26.000+0000", "created": "2015-01-08T22:21:19.000+0000", "priority": { "name": "Critical", "id": "1" }, "labels": [ "TCSupportTriage", "ios", "memory" ], "versions": [], "issuelinks": [], "assignee": { "name": "penrique", "key": "penrique", "displayName": "Pedro Enrique", "active": false, "timeZone": "America/Los_Angeles" }, "updated": "2017-03-22T21:46:32.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "10206", "name": "iOS", "description": "iOS Platform" } ], "description": "PROBLEM:\n\nWhen you want to read or write a file using FileStream.read(buffer) and FileStream.write(buffer), the memory used to store the data read/written is leaked, leading to a crash after writing/reading files for a few minutes.\n\nTEST CASE:\n\nThis is how the file is read:\n{code}\nwhile (true) {\n\t\t\n\t\tvar file = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, \"image.png\");\n\t\tvar fileStream = file.open(Ti.Filesystem.MODE_READ);\n\t\tvar buffer = Ti.createBuffer({\n\t\t\tlength: 1024 * 10\n\t\t});\n\t\t\n\t\twhile (fileStream.read(buffer) > 0) {}\n\t\t\n\t\tfile = null;\n\t\tfileStream.close();\n\t\tfileStream = null;\n\t\tbuffer.release();\n\t\tbuffer = null;\n}\n{code}\nThis is how the file is written:\n{code}\nwhile (true) {\n\t\t\n\t\tvar file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, \"output.txt\");\n\t\tvar fileStream = file.open(Ti.Filesystem.MODE_WRITE);\n\t\tvar buffer = Ti.createBuffer({\n\t\t\tvalue: \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut nisi felis, ultrices nec blandit vitae, efficitur a lacus. Nunc nec neque eleifend, aliquam leo id, scelerisque dolor. Suspendisse potenti. Pellentesque feugiat volutpat dictum. Morbi et massa venenatis lectus sodales maximus. In id ornare justo. Duis a nulla tincidunt, laoreet leo nec, aliquam ex. Nunc condimentum tellus justo, non efficitur magna viverra sit amet. Sed lectus neque, placerat non posuere in, faucibus quis nisl. Aliquam lobortis est eget felis varius, a placerat ex interdum. Aenean sit amet tempor turpis. Fusce at faucibus nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Phasellus lacus enim, efficitur eget egestas vitae, viverra vel neque. Donec orci lacus, consectetur sit amet placerat vel, pharetra nec odio. Quisque tempus nulla diam, id aliquet tellus pharetra et. Pellentesque id urna non nisi commodo aliquam. Praesent nec porttitor metus, ac finibus purus. Curabitur vel magna libero. Duis cursus diam sapien, eu finibus erat rutrum sed. Fusce viverra dictum erat cursus finibus. Maecenas lobortis neque libero, et porttitor tortor tincidunt eu. Mauris commodo interdum urna ac egestas. Fusce vehicula egestas risus et efficitur. Suspendisse nisl ex, sagittis nec neque vitae, malesuada vulputate justo. Vivamus aliquet lorem tellus, et convallis felis sollicitudin a. Vestibulum non lacus ut metus placerat feugiat vel sit amet nunc. Pellentesque vestibulum, turpis nec feugiat tincidunt, arcu lorem iaculis felis, eget mattis arcu nunc non mi. Phasellus eros erat, condimentum nec varius ac, eleifend non tortor. Nunc pellentesque purus non lorem ultrices rhoncus. Integer in efficitur dolor. Aenean laoreet et dolor placerat accumsan.\"\n\t\t});\n\t\t\n\t\tvar bytesWritten = 0;\n\t\twhile (bytesWritten < 1024*1014) {\n\t\t\tbytesWritten += fileStream.write(buffer);\n\t\t}\n\t\t\n\t\tfile = null;\n\t\tfileStream.close();\n\t\tfileStream = null;\n\t\tbuffer.release();\n\t\tbuffer = null;\n\t\t\n\t}\n{code}\nIn both cases the heap grows until the app crashes. I've attached an image which shows how the heap grows.", "attachment": [ { "id": "53489", "filename": "instruments-heap-grow.png", "author": { "name": "tola.ware", "key": "tola.ware", "displayName": "Fernando Manzano", "active": true, "timeZone": "America/Argentina/Buenos_Aires" }, "created": "2015-01-08T22:21:19.000+0000", "size": 280639, "mimeType": "image/png" } ], "flagged": false, "summary": "iOS: FileStream Significant memory leak while reading/writing files using FileStream", "creator": { "name": "tola.ware", "key": "tola.ware", "displayName": "Fernando Manzano", "active": true, "timeZone": "America/Argentina/Buenos_Aires" }, "subtasks": [], "reporter": { "name": "tola.ware", "key": "tola.ware", "displayName": "Fernando Manzano", "active": true, "timeZone": "America/Argentina/Buenos_Aires" }, "environment": "Titanium SDK version: 3.4.1.GA\r\nJavascript Engine: V8\r\nPlatform & version: iOS 7.0, iOS 8.0, Android 2.3.4, Android 4.4\r\nDevice Details: iPhone 4S, iPhone 5S, Nexus 5, Samsung S2\r\nHost Operating System: OS X 10.10.1\r\nTitanium Studio version: 3.4.1.201410281743", "closedSprints": [ { "id": 536, "state": "closed", "name": "2015 Sprint 25 SDK", "startDate": "2015-12-05T01:30:40.415Z", "endDate": "2015-12-19T01:30:00.000Z", "completeDate": "2015-12-29T03:19:42.127Z", "originBoardId": 114 } ], "comment": { "comments": [ { "id": "372350", "author": { "name": "penrique", "key": "penrique", "displayName": "Pedro Enrique", "active": false, "timeZone": "America/Los_Angeles" }, "body": "I do not see a bug here, the code is not realistic and it is creating a memory leak. Let me explain; by creating a {{while(true)}} you're not allowing the javascript engine to do its garbage collection, and thus creating a memory leak, infinite loop, etc. A better test case would be to create a {{setInterval}} instead\r\n{code}\r\nsetInterval(function() {\r\n // code here\r\n},100);\r\n{code}\r\nI tested this and the allocation in instruments do not go up.\r\n", "updateAuthor": { "name": "penrique", "key": "penrique", "displayName": "Pedro Enrique", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2015-12-07T22:48:08.000+0000", "updated": "2015-12-07T22:48:08.000+0000" }, { "id": "415037", "author": { "name": "lmorris", "key": "lmorris", "displayName": "Lee Morris", "active": false, "timeZone": "America/Los_Angeles" }, "body": "Closing ticket as invalid with reference to previous comments.", "updateAuthor": { "name": "lmorris", "key": "lmorris", "displayName": "Lee Morris", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2017-03-22T21:46:32.000+0000", "updated": "2017-03-22T21:46:32.000+0000" } ], "maxResults": 4, "total": 4, "startAt": 0 } } }