Hi Marcel
I am using MBM modem in oFono and I have run into a problem with
reopen_callback(..) function.
I think you might be interested in looking into this as an author
of the code.
The situation is as follow:
1. connect modem to USB port
2. Power the modem up: Modem.SetProperty( Powered = True )
2a. oFono is in the middle of enabling process
3. disconnect modem from USB port
2b. oFono is still in the middle of enabling process, and modem is not marked
as enabled
4. mbm_disconnect(..) is called, gprs atom removed, reopen_callback(..) is set
to be called in 1 second delay with data->reopen_source timer
5. mbm_remove(..) is called, notice that at this point the mbm_disable(..)
function call is not called as modem is not enabled yet, and the
reopen_callback 1 second timer is still running.
6. timer expiries and as a result reopen_callback(..) is called. At this
point modem is already removed and function accesses an already
freed memory
7. oFono crashes with segmentation fault
Normally reopen_callback timer would be removed in mbm_disable(..) called
if enabling process has finished.
The easy solution is to add removal of reopen_callback timer in mbm_remove(..)
but I can imagine a race condition then. It might happen that during heavy load
time between mbm_disconnect(..) and mbm_disable(..) or mbm_remove(..) can
be longer than 1 second resulting in call to reopen_callback(..) during hardware
disconnection process. Though I am not sure what can happen here, if this will
result in segmentation fault or it would just execute without any side effects.
I have also noticed that other vendors don't go with delayed
reopen_collback(..) at all. They usually try to reopen directly
in mbm_disconnect(..).
Best regards
Tomasz Gregorek
ST-Ericsson
Below an example of log from oFono and some gdb data with source code of
reopen_callback(..) and mbm_disconnect(..) as reference.
[1]
ofonod[1735]: plugins/mbm.c:mbm_probe() 0x812ce58
ofonod[1735]: plugins/smart-messaging.c:modem_watch() modem: 0x812ce58, added: 1
ofonod[1735]: plugins/push-notification.c:modem_watch() modem: 0x812ce58,
added: 1
ofonod[1735]: plugins/mbm.c:mbm_enable() 0x812ce58
ofonod[1735]: src/modem.c:get_modem_property() modem 0x812ce58 property
ModemDevice
ofonod[1735]: src/modem.c:get_modem_property() modem 0x812ce58 property
DataDevice
[2] ofonod[1735]: plugins/mbm.c:mbm_enable() /dev/ttyACM1, /dev/ttyACM0
ofonod[1735]: Modem: > AT\r
ofonod[1735]: Data: > AT\r
ofonod[1735]: Data: < \r\nOK\r\n
ofonod[1735]: Data: > AT&F E0 V1 X4 &C1 +CMEE=1\r
ofonod[1735]: Data: < AT&F E0 V1 X4 &C1 +CMEE=1\r
ofonod[1735]: Data: < \r\nOK\r\n
[3]
[4] ofonod[1735]: plugins/mbm.c:mbm_disconnect() mbm_disconnect
******************************************
ofonod[1735]: plugins/udev.c:remove_modem()
/devices/pci0000:00/0000:00:0b.0/usb1/1-1/1-1:1.1/tty/ttyACM0
ofonod[1735]: src/modem.c:get_modem_property() modem 0x812ce58 property Path
ofonod[1735]: src/modem.c:ofono_modem_remove() 0x812ce58
[5] ofonod[1735]: plugins/mbm.c:mbm_remove() 0x812ce58
ofonod[1735]: src/modem.c:unregister_property() property 0x812ded8
ofonod[1735]: src/modem.c:unregister_property() property 0x812d2d0
ofonod[1735]: src/modem.c:unregister_property() property 0x812c988
ofonod[1735]: src/modem.c:unregister_property() property 0x812d080
ofonod[1735]: src/modem.c:unregister_property() property 0x812cee0
ofonod[1735]: plugins/smart-messaging.c:modem_watch() modem: 0x812ce58, added: 0
ofonod[1735]: plugins/push-notification.c:modem_watch() modem: 0x812ce58,
added: 0
ofonod[1735]: plugins/udev.c:remove_modem()
/devices/pci0000:00/0000:00:0b.0/usb1/1-1/1-1:1.3/tty/ttyACM1
ofonod[1735]: plugins/udev.c:remove_modem()
/devices/pci0000:00/0000:00:0b.0/usb1/1-1/1-1:1.6/net/usb0
[6] ofonod[1735]: plugins/mbm.c:reopen_callback() reopen_callback
******************************************
[7]
Program received signal SIGSEGV, Segmentation fault.
0x080a7927 in reopen_callback (user_data=0x812ce58) at plugins/mbm.c:318
318 data->reopen_source = 0;
(gdb) p data
$1 = (struct mbm_data *) 0x2d303336
(gdb) p *data
Cannot access memory at address 0x2d303336
(gdb) p *modem
$2 = {path = 0x812e468 "", modem_state = 135453480, atoms = 0x2f6c6169,
atom_watches = 0x692d7962, interface_list = 0x73752f64,
feature_list = 0x54532d62, call_ids = 1769096493, pending = 0x6f737363,
interface_update = 1414750062, powered = 1769096493,
powered_pending = 1869837155, timeout = 1867341678, online = 1701603682,
online_watches = 0x6f72425f, properties = 0x61626461,
sim = 0x465f646e, sim_watch = 1160788025, sim_ready_watch = 876754743, driver
= 0x36454432, driver_data = 0x2d303336,
driver_type = 0x33306669 <Address 0x33306669 out of bounds>, name = 0x0}
(gdb) l 305,361
305 static void mbm_disconnect(gpointer user_data);
306
307 static gboolean reopen_callback(gpointer user_data)
308 {
309 struct ofono_modem *modem = user_data;
310 struct mbm_data *data = ofono_modem_get_data(modem);
311 const char *data_dev;
312
313 DBG("reopen_callback
******************************************");
314
315 //if(!data)
316 // return FALSE;
317
318 data->reopen_source = 0;
319
320 data_dev = ofono_modem_get_string(modem,
"DataDevice");
321
322 data->data_port = create_port(data_dev);
323 if (data->data_port == NULL)
324 return FALSE;
325
326 if (getenv("OFONO_AT_DEBUG"))
327 g_at_chat_set_debug(data->data_port,
mbm_debug, "Data: ");
328
329 g_at_chat_set_disconnect_function(data->data_port,
330
mbm_disconnect, modem);
331
332 ofono_info("Reopened GPRS context channel");
333
334 data->gc = ofono_gprs_context_create(modem, 0,
335
"atmodem", data->data_port);
336 if (data->gprs && data->gc) {
337 ofono_gprs_context_set_type(data->gc,
338
OFONO_GPRS_CONTEXT_TYPE_MMS);
339 ofono_gprs_add_context(data->gprs,
data->gc);
340 }
341
342 return FALSE;
343 }
344
345 static void mbm_disconnect(gpointer user_data)
346 {
347 struct ofono_modem *modem = user_data;
348 struct mbm_data *data = ofono_modem_get_data(modem);
349
350 DBG("mbm_disconnect
******************************************");
351
352 if (data->gc)
353 ofono_gprs_context_remove(data->gc);
354 //data->gc = NULL;
355
356 g_at_chat_unref(data->data_port);
357 data->data_port = NULL;
358
359 /* Waiting for the +CGEV: ME DEACT might also work */
360 data->reopen_source = g_timeout_add_seconds(5,
reopen_callback, modem);
361 }
(gdb)
_______________________________________________
ofono mailing list
[email protected]
http://lists.ofono.org/listinfo/ofono