void LibraryMenuItem::onClose() { setAlphaAnim(getStyle().getAlpha(), 0.0f, 15, (FinishedCallBack) RemoveLayoutItemAfterAnim, getParent()); if (winOS->GetLibraryManager()) { RemoveLibrary(_library); GLOBAL(settings).otherLibraries = winOS->GetLibraryManager()->getFolderLibraryDirectories(); winOS->SaveSettingsFile(); } }
/* void disconnect (); */ nsresult sbMockDevice::DeviceSpecificDisconnect() { NS_ENSURE_STATE(mIsConnected); nsresult rv; nsRefPtr<sbBaseDeviceVolume> volume; { nsAutoLock autoVolumeLock(mVolumeLock); volume = mDefaultVolume; mDefaultVolume = nsnull; } if (volume) RemoveVolume(volume); mIsConnected = PR_FALSE; // Finalize the device content and device libraries if (mContent) { // Get a copy of the list of device libraries nsCOMArray<sbIDeviceLibrary> libraryListCopy; PRInt32 libraryListCopyCount; nsCOMPtr<nsIArray> libraryList; PRUint32 libraryCount; rv = mContent->GetLibraries(getter_AddRefs(libraryList)); if (NS_SUCCEEDED(rv)) rv = libraryList->GetLength(&libraryCount); if (NS_SUCCEEDED(rv)) { for (PRUint32 i = 0; i < libraryCount; i++) { nsCOMPtr<sbIDeviceLibrary> library = do_QueryElementAt(libraryList, i, &rv); if (NS_FAILED(rv)) continue; libraryListCopy.AppendObject(library); } } libraryListCopyCount = libraryListCopy.Count(); // Finalize each device library for (PRInt32 i = 0; i < libraryListCopyCount; i++) { RemoveLibrary(libraryListCopy[i]); FinalizeDeviceLibrary(libraryListCopy[i]); } // Finalize the device content mContent->Finalize(); mContent = nsnull; } PRUint32 state = sbIDevice::STATE_IDLE; nsCOMPtr<sbIDeviceManager2> manager = do_GetService("@songbirdnest.com/Songbird/DeviceManager;2", &rv); NS_ENSURE_SUCCESS(rv, rv); sbNewVariant data(static_cast<sbIDevice*>(static_cast<sbBaseDevice*>(this))); nsCOMPtr<sbIDeviceEvent> deviceEvent; rv = manager->CreateEvent(sbIDeviceEvent::EVENT_DEVICE_REMOVED, sbNewVariant(static_cast<sbIDevice*>(static_cast<sbBaseDevice*>(this))), data, state, state, getter_AddRefs(deviceEvent)); NS_ENSURE_SUCCESS(rv, rv); bool dispatched; rv = DispatchEvent(deviceEvent, PR_TRUE, &dispatched); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; }
/* Handle breakpoints - we expect to see breakpoints in the dynamic linker * (which we set ourselves) as well as profiler marks (embedded in the * profiled application's code). */ static bool ProcessBreakpoint( pid_t pid, u_long ip ) { static int ld_state = RT_CONSISTENT; // This ought to be per-pid int ptrace_sig = 0; #if defined( MD_x86 ) user_regs_struct regs; // on x86, when breakpoint was hit the EIP points to the next // instruction, so we must be careful ptrace( PTRACE_GETREGS, pid, NULL, ®s ); if( ip == Rdebug.r_brk + sizeof( opcode_type ) ) { #elif defined( MD_ppc ) if( ip == Rdebug.r_brk ) { #endif opcode_type brk_opcode = BRKPOINT; int status; int ret; /* The dynamic linker breakpoint was hit, meaning that * libraries are being loaded or unloaded. This gets a bit * tricky because we must restore the original code that was * at the breakpoint and execute it, but we still want to * keep the breakpoint. */ if( WriteMem( pid, &saved_opcode, Rdebug.r_brk, sizeof( saved_opcode ) ) != sizeof( saved_opcode ) ) printf( "WriteMem() #1 failed\n" ); ReadMem( pid, &Rdebug, (addr_off)DbgRdebug, sizeof( Rdebug ) ); dbg_printf( "ld breakpoint hit, state is " ); switch( Rdebug.r_state ) { case RT_ADD: dbg_printf( "RT_ADD\n" ); AddLibrary( pid, Rdebug.r_map ); ld_state = RT_ADD; break; case RT_DELETE: dbg_printf( "RT_DELETE\n" ); ld_state = RT_DELETE; break; case RT_CONSISTENT: dbg_printf( "RT_CONSISTENT\n" ); if( ld_state == RT_DELETE ) RemoveLibrary( pid, Rdebug.r_map ); ld_state = RT_CONSISTENT; break; default: dbg_printf( "error!\n" ); break; } #if defined( MD_x86 ) regs.eip--; ptrace( PTRACE_SETREGS, pid, NULL, ®s ); #endif // unset breakpoint, single step, re-set breakpoint if( ptrace( PTRACE_SINGLESTEP, pid, NULL, (void *)ptrace_sig ) < 0 ) perror( "ptrace()" ); do { // have to loop since SIGALRM can interrupt us here ret = waitpid( pid, &status, 0 ); } while( (ret < 0) && (errno == EINTR) ); if( ret == -1) perror( "waitpid()" ); if( WriteMem( pid, &brk_opcode, Rdebug.r_brk, sizeof( brk_opcode ) ) != sizeof( brk_opcode ) ) dbg_printf( "WriteMem() #2 failed with errno %d for pid %d, %d bytes (at %p)!\n", errno, pid, sizeof( brk_opcode ), Rdebug.r_brk ); return( true ); // indicate this was our breakpoint } else { dbg_printf( "Not an ld breakpoint, assuming mark\n" ); #if defined( MD_x86 ) return( ProcessMark( pid, ®s ) ); #endif } return( false ); } /* * Real time signal (SIGALRM) handler. All we really need to do is wake up * periodically to interrupt waitpid(), the signal handler need not do much * at all. */ static void alarm_handler( int signo ) { TimerTicked = true; } /* Install periodic real time alarm signal */ static void InstSigHandler( int msec_period ) { struct sigaction sigalrm; struct itimerval timer; sigalrm.sa_handler = (void *)alarm_handler; sigemptyset( &sigalrm.sa_mask ); sigalrm.sa_flags = 0; sigaction( SIGALRM, &sigalrm, NULL ); timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = msec_period * 1000; timer.it_value.tv_sec = 0; timer.it_value.tv_usec = msec_period * 1000; if( setitimer( ITIMER_REAL, &timer, NULL ) ) { InternalError( MsgArray[MSG_SAMPLE_6 - ERR_FIRST_MESSAGE] ); } } /* * Main sampler loop. We run the profiled application under the control of * ptrace(). The sampler installs a SIGALRM handler which ticks at the desired * rate. Whenever the SIGALRM interrupts our own waitpid(), we send a SIGSTOP * to the profiled app and when the child app notifies us of the SIGSTOP, we * remember the current execution point and continue the profiled app. Note * that we may miss some ticks but this is not a problem - the ticks don't * even need to be regular to provide usable results. */ static void SampleLoop( pid_t pid ) { static int ptrace_sig = 0; static bool do_cont = true; int status; user_regs_struct regs; bool sample_continue = true; int ret; opcode_type brk_opcode = BRKPOINT; TimerTicked = false; InstSigHandler( SleepTime ); do { if( do_cont && ptrace( PTRACE_CONT, pid, NULL, (void *)ptrace_sig ) == -1) perror( "ptrace()" ); ret = waitpid( pid, &status, 0 ); if( (ret < 0) && (errno == EINTR) ) { /* did we get woken up by SIGALRM? */ if( TimerTicked ) { TimerTicked = false; /* interrupt child process - next waitpid() will see this */ kill( pid, SIGSTOP ); } else { dbg_printf( "who the hell interrupted waitpid()?\n" ); } do_cont = false; continue; } if( ret < 0 ) perror( "waitpid()" ); do_cont = true; /* record current execution point */ #if defined( MD_x86 ) ptrace( PTRACE_GETREGS, pid, NULL, ®s ); #elif defined( MD_ppc ) regs.eip = ptrace( PTRACE_PEEKUSER, pid, REGSIZE * PT_NIP, NULL ); #endif if( WIFSTOPPED( status ) ) { /* If debuggee has dynamic section, try getting the r_debug struct * every time the child process stops. The r_debug data may not be * available immediately after the child process first loads. */ if( !HaveRdebug && (DbgDyn != NULL) ) { if( Get_ld_info( pid, DbgDyn, &Rdebug, &DbgRdebug ) ) { AddLibrary( pid, Rdebug.r_map ); HaveRdebug = true; /* Set a breakpoint in dynamic linker. That way we can be * informed on dynamic library load/unload events. */ ReadMem( pid, &saved_opcode, Rdebug.r_brk, sizeof( saved_opcode ) ); dbg_printf( "setting ld breakpoint at %p, old opcode was %X\n", Rdebug.r_brk, saved_opcode ); WriteMem( pid, &brk_opcode, Rdebug.r_brk, sizeof( brk_opcode ) ); } } sample_continue = false; switch( (ptrace_sig = WSTOPSIG( status )) ) { case SIGSEGV: dbg_printf( "SIGSEGV at %p\n", regs.eip ); sample_continue = true; break; case SIGILL: dbg_printf( "SIGILL at %p\n", regs.eip ); sample_continue = true; break; case SIGABRT: dbg_printf( "SIGABRT at %p\n", regs.eip ); sample_continue = true; break; case SIGINT: dbg_printf( "SIGINT at %p\n", regs.eip ); sample_continue = true; break; case SIGTRAP: dbg_printf( "SIGTRAP at %p\n", regs.eip ); if( ProcessBreakpoint( pid, regs.eip ) ) { // don't pass on SIGTRAP if we expected this breakpoint ptrace_sig = 0; } sample_continue = true; break; case SIGSTOP: /* presumably we were behind this SIGSTOP */ RecordSample( regs.eip, 1 ); ptrace_sig = 0; sample_continue = true; break; default: /* all other signals get passed down to the child and we let * the child handle them (or not handle and die) */ sample_continue = true; break; } } else if( WIFEXITED( status ) ) { dbg_printf( "WIFEXITED pid %d\n", pid ); report(); sample_continue = false; } else if( WIFSIGNALED( status ) ) { dbg_printf( "WIFSIGNALED pid %d\n", pid ); report(); sample_continue = false; } } while( sample_continue ); } static int GetExeNameFromPid( pid_t pid, char *buffer, int max_len ) { char procfile[24]; int len; sprintf( procfile, "/proc/%d/exe", pid ); len = readlink( procfile, buffer, max_len ); if( len < 0 ) len = 0; buffer[len] = '\0'; return( len ); }